wait ()와 sleep ()의 차이점


1203

스레드 wait()sleep()스레드 의 차이점은 무엇입니까 ?

wait()-ing 스레드가 여전히 실행 모드이고 CPU 사이클을 사용하지만 sleep()-ing이 CPU 사이클을 올바르게 소비하지 않는다는 것을 이해하고 있습니까?

왜 우리는 다음 과 같은 두 가지를 모두 가지고 있습니까?wait()sleep()


50
아주 좋은 질문입니다. 두 가지의 의미는 혼동하기 쉽습니다.
Andreas Petersson

1
아주 좋은 질문이지만 둘 중 하나입니다. 왜 우리 둘 다가 하위 레벨에서 구현할 수 있고 구현되지 않았는지와 동일하지 않은 이유는 무엇입니까? 나는 그것에 대해서도 대답했다.
estani

스레드 A가 동기화 된 블록에 있고이 스레드에서 CPU에있는 동안 다른 스레드 B에 제공되었다고 가정합니다. 이제 스레드 A가 진행되는 상태에서이 동기화 된 블록을 대기중인 다른 스레드가 이제 내부에 들어옵니다. ?
피터

1
여기에 좋은 기사가 있습니다 : qat.com/using-waitnotify-instead-thread-sleep-java
Triton Man

3
그 EXCATLY 반대 - 잠은 "용도"는 사용 가능한 CPU 사이클의 모든하지만 스레드가 "대기"에있을 것입니다 때문에 이러한 - 상태는 필요한 경우 산출 할 수있다 - 사실 대부분의 시스템이 자동으로주기를 산출 운영 IF 가 가능하며, 따라서 스레드는 실제 CPU로드를 생성하지 않습니다 ...하지만 오래된 운영 체제에서는 그렇게합니다. 로 Object.wait ()는, 다른 한편으로는 결코 어떤 사이클을 사용하지 않습니다 (잠시 unnotified 인) 그게 전부가 많은 경우에 소프트웨어 인터럽트를 통해 실현 때문에 - 개인, 과도 및 투명 잠금 장치, JVM에 의해 구현. Thread.sleep은 나쁜 연습입니다.
specializt

답변:


837

A waitnotify대기중인 모니터를 호출하는 다른 스레드에 의해 "깨어날"수 있습니다 sleep. 또한 wait(및 notify)는 synchronized모니터 객체 의 블록 에서 발생해야 하지만 다음과 같은 sleep것은 아닙니다.

Object mon = ...;
synchronized (mon) {
    mon.wait();
} 

이 시점에서 현재 실행중인 스레드는 모니터를 대기 하고 해제합니다 . 다른 스레드가 할 수 있습니다

synchronized (mon) { mon.notify(); }

(동일한 mon객체에서) 첫 번째 스레드 (모니터에서 대기중인 스레드 만 가정)가 깨어납니다.

notifyAll모니터에서 둘 이상의 스레드가 대기중인 경우 에도 호출 할 수 있습니다. 이렇게하면 모든 스레드가 깨어 납니다 . 그러나, 스레드 중 하나만합니다 (이 기억 모니터를 잡을 수있을 것 waitsynchronized다른 사람이 그 때 모니터의 잠금을 획득 할 수있을 때까지 차단됩니다 - 블록)와 계속.

또 다른 점은 전화 할 것입니다 waitObject당신이 전화를하는 반면 (즉, 당신이 객체의 모니터에서 대기) 자체 sleepThread.

또 다른 요점은 가짜 웨이크 업 을 얻을 수 있다는 것 입니다 wait(즉, 대기중인 스레드가 명백한 이유없이 재개됩니다). 다음과 같이 항상 wait어떤 상태에서 회전 해야 합니다.

synchronized {
    while (!condition) { mon.wait(); }
}

131
아닙니다. 인터럽트 만 가능합니다.
Peter Štibraný

9
중단 할 때 중단하려는 스레드를 알아야합니다. notify를 호출 할 때 객체가 필요 하며이 객체에서 '대기'하는 다른 스레드가 있는지는 신경 쓰지 않습니다. 대기 / 알림은 통신에 사용되고 수면은 ehm, 수면에 사용됩니다.
피터 Štibraný

28
@Geek-왜 세상에서 wait ()가 CPU 사이클을 낭비한다고 말합니까?
Robert Munteanu

25
인터럽트는 스레드가 완전히 실행을 멈추고 나머지 작업을 취소하도록 부드럽게하는 메커니즘으로 고안되었습니다. wait/ notify는 일반적으로 다른 스레드가 작업을 수행하거나 특정 조건이 충족 될 때까지 대기하는 데 사용됩니다.
Louis Wasserman

13
나는 모든 대답을 읽었지만 여전히 약간의 정보가 빠져 있다고 느낍니다. 많은 사람들이 Javadoc의 정의와 두 영어 단어의 의미를 적어 보았지만 왜 대기 대신 잠을 사용해야합니까? 둘 사이의 벤치마킹 및 속도 차이는 무엇입니까? 수면으로 할 수있는 모든 것을 할 수 있다면 왜 수면을 선택해야합니까?
Balazs Zsoldos

334

아직 언급되지 않은 한 가지 주요 차이점은 스레드를자는 동안 스레드가 보유한 잠금을 해제 하지 않고 대기하는 동안 wait()호출 되는 객체의 잠금을 해제한다는 것 입니다.

synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}

105
대기 wait () 를 호출 하는 객체에 대한 잠금 만 해제합니다 . 다른 잠금 은 해제하지 않습니다 .
Jon Skeet

16
실제로 잠금 내에서 수면을 호출 할 필요는 없습니다. 잠금 및 대기 / 알림은 동시에 진행되지만 잠금과 수면은 관련이 없습니다.
oxbow_lakes

7
@oxbow_lakes-자물쇠로 잠을 자면 안된다고 말하지만 그 사용 사례는 거의 없습니다. 차이점을 지적하고 싶었습니다.
Robert Munteanu

5
@RobertMunteanu, 귀하의 답변 sleepJava 잠금 을 보유하고 있다고 오도하게 주장 하지만 그렇지 않습니다. 공정한 비교를 위해, 우리는 비교 것 synchronized(OUTER_LOCK){ Thread.sleep(1000); }와 함께 synchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }우리는 모두 지침은 공개하지 않는 것을 볼 수 있습니다 OUTER_LOCK. 차이점이 있다면 sleep명시 적으로 Java 잠금을 사용 하지 않는다고 말할 수 는 있지만, "구현 수준이 어떻게 다른가 ?" 인용을 해제하십시오.
Pacerier

2
@Pacerier wait()는 코드 예제에서 호출 된 가장 안쪽 잠금 상태와 관련이 있으며 wait()해제 할 수는 LOCK없습니다 OUTER_LOCK. 어쨌든 Java 모니터가 설계된 방식입니다. 공정한 비교는 synchronized(OUTER_LOCK){ synchronized(LOCK) { Thread.sleep(1000); } }and synchronized(OUTER_LOCK){ synchronized(LOCK) { LOCK.wait(); } }입니다. 이 사건에서 sleep()동안 모두 잠금을 개최합니다 wait()발표 할 예정이다 LOCK하지만 여전히 유지OUTER_LOCK
danze

243

나는 발견 이 게시물이 도움이. 그것은 차이두고 Thread.sleep(), Thread.yield()그리고 Object.wait()인간의 측면에서입니다. 인용 :

결국 모든 프로세스와 스레드에 타임 슬라이스를 전달하는 OS 스케줄러로 넘어갑니다.

sleep(n)말한다 "나는 내 타임 슬라이스로 끝났어요, 그리고 나에게 최소한 n 밀리 초 또 다른 하나를 포기하지 마십시오." OS는 요청 된 시간이 지날 때까지 슬리핑 스레드를 예약하지 않습니다.

yield()말한다 "나는 내 타임 슬라이스로 끝났어요,하지만 난 아직 할 일이 있습니다." OS는 스레드에 즉시 다른 타임 슬라이스를 제공하거나 다른 스레드를 제공하거나 CPU가 처리 한 스레드가 방금 포기한 프로세스를 처리 할 수 ​​있습니다.

wait()라고 내 타임 슬라이스로 끝났어요. " 누군가 notify ()를 호출 할 때까지 다른 타임 슬라이스를주지 마십시오.” 와 마찬가지로 sleep()OS는 누군가가 전화하지 않으면 notify()(또는 다른 웨이크 업 시나리오 중 하나가 발생 하지 않는 한) 작업 예약을 시도하지도 않습니다 .

스레드는 IO 차단 및 기타 상황에서 나머지 타임 슬라이스를 잃습니다. 스레드가 전체 시간 조각을 통해 작동하는 경우 OS는 마치 마치 yield()호출 된 것처럼 대략적으로 제어 하여 다른 프로세스를 실행할 수 있습니다.

거의 필요하지 않지만 yield()논리적 인 작업 경계를 가진 계산량이 많은 앱을 사용하는 경우 시스템 응답 속도를 향상시킬 yield() 수 있습니다 . 항상 그렇듯이 관심있는 목표를 측정하고 테스트하십시오.


수율은 기본적으로 플랫폼에 따라 다릅니다 ... javamex.com/tutorials/threads/yield.shtml
Pacerier

에 대한 설명은 sleep(n)현재 실행중인 스레드가 잠금 모니터를 자발적으로 포기한다는 것을 암시 적으로 말하지만 사실아닙니다 . 스레드의 javadoc 에서 인용 : "스레드는 모니터의 소유권을 잃지 않습니다."
클린트 이스트우드

2
@Jonathan은 대답에 모니터에 대한 언급이 없으며 sleep다른 Java 메소드 호출보다 모니터와 관련하여 특별한 동작 이 없기 때문에 어떤 방식 으로든 상호 작용하거나 수정하지 않습니다. 모니터에 대해 언급하려는 경우 wait위에서 언급 한 것 외에도 호출 된 오브젝트의 잠금을 일시적으로 포기하도록 지정해야합니다 .
pqnet

알림은 OS 스케줄러 수준에서 어떻게 작동합니까? 스케줄러가 관련 스레드를 실행중인 큐에 다시 넣을 수 있도록 특정 스레드 ID를 가진 일종의 이벤트 핸들러를 알리십시오. 또 다른 질문이 있는데 spinlock의 개념은 어디에 적합합니까? 수면에만 관련이 있습니까 아니면 대기 자체가 매우 낮은 수준에서 스핀 록을 사용합니까?
CMCDragonkai

@Erich, wait(n)와 비교하는 데 사용 합니다 sleep(n). 인수없는 것을 사용하는 것을 비교하는 것은 의미가 없습니다.
Pacerier

68

여기에 많은 대답이 있지만 언급 된 의미 론적 차이점을 찾을 수 없습니다.

스레드 자체에 관한 것이 아닙니다. 서로 다른 사용 사례를 지원하므로 두 가지 방법이 모두 필요합니다.

sleep()스레드를 이전과 같이 휴면 상태로 보내고 컨텍스트를 압축하고 미리 정의 된 시간 동안 실행을 중지합니다. 따라서 마감 시간 전에 깨우려면 스레드 참조를 알아야합니다. 다중 스레드 환경에서는 일반적인 상황이 아닙니다. 주로 시간 동기화 (예 : 정확히 3.5 초 깨우기) 및 / 또는 하드 코딩 된 공정성 (잠시 동안 잠자기 및 다른 스레드가 작동하도록 함)에 사용됩니다.

wait()반대로, 스레드 (또는 메시지) 동기화 메커니즘은 저장된 참조 (또는 관리)가없는 스레드를 통지 할 수있게합니다. 이것을 publish-subscribe 패턴 ( wait== subscribe 및 notify()== publish) 으로 생각할 수 있습니다 . 기본적으로 notify ()를 사용하면 메시지를 보내고 있습니다 (아직 전혀받지 못하고 일반적으로 상관하지 않습니다).

요약하면 일반적으로 sleep()시간 동기화 및 wait()다중 스레드 동기화에 사용합니다.

그것들은 기본 OS에서 동일한 방식으로 구현되거나 전혀 구현되지 않을 수 있습니다 (이전 버전의 Java에는 실제 멀티 스레딩이 없었기 때문에 일부 작은 VM도 그렇게하지 않습니다). VM에서 Java 실행을 잊지 마십시오. 코드는 VM / OS / HW에 따라 다르게 변환됩니다.


54

여기에 wait()sleep()메소드 사이의 중요한 차이점이 거의 없습니다 .
추신 : 또한 링크를 클릭하여 라이브러리 코드를 확인하십시오 (내부 작업, 이해를 돕기 위해 조금만 놀아보십시오).

기다림()

  1. wait() 메소드는 잠금을 해제합니다.
  2. wait()Object클래스 의 방법입니다 .
  3. wait() 비 정적 방법입니다- public final void wait() throws InterruptedException { //...}
  4. wait()notify()또는 notifyAll()방법 으로 통지해야합니다 .
  5. wait() 잘못된 경보를 처리하려면 루프에서 메소드를 호출해야합니다.

  6. wait() 동기화 된 컨텍스트에서 메소드를 호출해야합니다 (예 : 동기화 된 메소드 또는 블록). 그렇지 않으면 IllegalMonitorStateException

자다()

  1. sleep() 메소드는 잠금을 해제하지 않습니다.
  2. sleep()java.lang.Thread클래스 의 방법입니다 .
  3. sleep() 정적 방법입니다- public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  4. 지정된 시간이 지나면 sleep() 완료됩니다.
  5. sleep()루프에서 호출하지 않는 것이 좋습니다 (즉, 아래 코드 참조 ).
  6. sleep()어디서나 호출 될 수 있습니다. 특정 요구 사항이 없습니다.

참고 : 대기와 수면의 차이점

대기 및 절전 메소드 호출을위한 코드 스 니펫

synchronized(monitor){
    while(condition == true){ 
        monitor.wait()  //releases monitor lock
    }

    Thread.sleep(100); //puts current thread on Sleep    
}

다른 스레드 상태로 스레드 전환


notify () 호출로 수면 스레드를 깨울 수있는 것이 맞습니까? 여기에있는 다른 게시물 중 일부는 잠자는 스레드를 깨울 수 없지만 중단되었음을 의미합니다.
berimbolo

예, Thread.sleep()다른 스레드에서 프로세서 시간을 사용할 수있게하는 데 사용됩니다. 휴면 기간은 인터럽트 (즉, JVM)에 의해 종료 될 수 있습니다. 이 stackoverflow.com/questions/4264355/…를
roottraveller

그 게시물은 또한 인터럽트 ()가 잠자는 스레드를 깨우는 것이라고 말합니다. 나는 당신이 게시 한 스레드 상태 다이어그램을 언급하고 있었다. 나는 단지 그것을 이해하고 싶다.
berimbolo

@berimbolo notify()또는 notifyAll()있는 Object클래스 메소드. 따라서 그들은 모든 클래스의 obj를 사용할 수 있습니다 (즉, 여기 Thread클래스도 있습니다). grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
roottraveller

2
OK 스레드 스레드를 깨우는 notify () 또는 notifyAll ()의 예제를 찾을 수 없으므로 스레드 스케줄링에 대해 더 읽어야합니다. 모든 예제는 notify () 및 notifyAll ()을 일부 모니터 오브젝트를 기다리는 스레드와 관련시킵니다.
berimbolo

29

대기 및 수면 작업을 마친 후 결론을 내리는 몇 가지 차이점이 있습니다. 먼저 wait () 및 sleep ()을 사용하여 샘플을 살펴보십시오.

예 1 : 대기 () 및 절전 () 사용

synchronized(HandObject) {
    while(isHandFree() == false) {
        /* Hand is still busy on happy coding or something else, please wait */
        HandObject.wait();
    }
}

/* Get lock ^^, It is my turn, take a cup beer now */
while (beerIsAvailable() == false) {
    /* Beer is still coming, not available, Hand still hold glass to get beer,
       don't release hand to perform other task */
    Thread.sleep(5000);
}

/* Enjoy my beer now ^^ */
drinkBeers();

/* I have drink enough, now hand can continue with other task: continue coding */
setHandFreeState(true);
synchronized(HandObject) {
    HandObject.notifyAll();
}

몇 가지 주요 사항을 명확하게 설명하십시오.

  1. 전화 :
    • wait () : HandObject 객체를 보유하는 현재 스레드 호출
    • sleep () : 스레드 실행 호출이 맥주를 얻습니다 (클래스 메소드이므로 현재 실행중인 스레드에 영향을 미침)
  2. 동기화 :
    • wait () : 동기화 된 다중 스레드 액세스 동일한 객체 (HandObject) 일 때 (동일한 객체에 대한 둘 이상의 스레드 간 통신이 필요한 경우 (스레드 실행 코딩, 스레드 실행 맥주) 액세스)
    • sleep () : 대기 조건이 계속 실행될 때 (대기 맥주 사용 가능)
  3. 잠금 유지 :
    • wait () : 다른 객체에 대한 잠금 해제 (HandObject는 무료, 다른 작업을 수행 할 수 있음)
    • sleep () : 적어도 t 번 (또는 중단 될 때까지) 잠금을 유지하십시오 (내 작업이 아직 완료되지 않았습니다.
  4. 웨이크 업 조건 :
    • wait () : 객체에서 notify (), notifyAll ()을 호출 할 때까지
    • sleep () : 적어도 시간이 지날 때까지 또는 호출 중단
  5. 그리고 마지막 점입니다 때 사용 으로 estani을 나타냅니다

일반적으로 시간 동기화에는 sleep ()을 사용하고 다중 스레드 동기화에는 wait ()를 사용합니다.

내가 틀렸다면 정정 해주세요.


25

wait ()와 sleep ()의 차이점

  • 기본적인 차이는 즉 wait()내지 Objectsleep()의 고정 방법 Thread.

  • 가장 큰 차이점은 wait()잠금을 sleep()해제하고 대기하는 동안 잠금을 해제하지 않는다는 것입니다.

  • wait()스레드 간 통신 sleep()에 사용되는 반면 일반적으로 실행 일시 중지를 도입하는 데 사용됩니다.

  • wait()내부 동기화 호출 그렇지 않으면 우리가 얻을해야 IllegalMonitorStateException하지만, sleep() 어디서든 호출 할 수 있습니다.

  • 에서 스레드를 다시 시작하려면 또는 wait()을 호출해야합니다 . 에 관해서는 스레드 지정된 시간 간격 후에 시작됩니다.notify()notifyAll()sleep(),

유사점

  • 둘 다 현재 스레드를 실행 불가능 상태로 만듭니다.
  • 둘 다 기본 방법입니다.

18

이 두 가지 방법은 완전히 다른 용도로 사용되기 때문에 이것은 매우 간단한 질문입니다.

가장 큰 차이점은 대기 중에 잠자기가 잠금 또는 모니터를 해제하지 않는 동안 잠금 또는 모니터를 놓기를 기다리는 것입니다. 대기는 스레드 간 통신에 사용되는 반면 대기는 실행시 일시 중지에 사용됩니다.

이것은 분명하고 기본적인 설명이었습니다. 그 이상을 원한다면 계속 읽으십시오.

의 경우에는 wait()방법 스레드를 대기 상태로 간다 그것은 우리가 호출 할 때까지 자동으로 다시 오지 않을 notify()방법을 (또는 notifyAll()당신이 대기 상태에 두 개 이상의 스레드가 있고 당신이 그 스레드의 모든 깨워하려는 경우). 그리고 당신은 동기화 또는 개체 잠금 또는 클래스 잠금 액세스에 필요 wait()하거나 notify()또는 notifyAll()방법. 그리고 한 가지 더는 wait()스레드가 대기 상태에가는 경우 스레드를 깨워 다른 스레드를해야하기 때문에 방법은 스레드 간 통신에 사용됩니다.

그러나이 경우 sleep()몇 초 동안 또는 원하는 시간 동안 프로세스를 유지하는 데 사용되는 방법입니다. 스레드를 다시 가져 오기 위해 notify()또는 notifyAll()메소드를 유발할 필요가 없기 때문입니다. 또는 해당 스레드를 다시 호출하기 위해 다른 스레드가 필요하지 않습니다. 사용자 차례 후 게임에서와 같이 몇 초 후에 어떤 일이 일어나기를 원한다면 컴퓨터가 재생 될 때까지 사용자가 기다리기를 원한다면 sleep()방법을 언급 할 수 있습니다 .

그리고 면접에서 자주 질문되는 또 하나의 중요한 차이점은 : sleep()에 속하는 Thread클래스 wait()에 속하는 Object클래스입니다.

이들 사이의 모든 차이가 있습니다 sleep()wait().

그리고 두 방법 사이에는 유사점이 있습니다. 두 방법 모두 검사 문이므로 검사하거나 던질 필요가 있습니다.

이것이 도움이되기를 바랍니다.


16

출처 : http://www.jguru.com/faq/view.jsp?EID=47127

Thread.sleep()현재 스레드 를 일정 시간 동안 "실행 불가능" 상태 로 보냅니다 . 스레드는 요청한 모니터를 유지합니다. 즉, 스레드가 현재 동기화 된 블록 또는 메소드에있는 경우 다른 스레드는이 블록 또는 메소드를 입력 할 수 없습니다. 다른 스레드가 호출하는 경우t.interrupt() 하면 잠자는 스레드를 깨 웁니다.

sleep은 정적 메소드이므로 항상 현재 스레드 (sleep 메소드를 실행중인 스레드)에 영향을 미칩니다. 일반적인 실수는 t.sleep()t가 다른 스레드 인 곳 을 호출 하는 것입니다 . 그럼에도 불구하고 t 스레드가 아닌 현재 스레드입니다.

t.suspend()더 이상 사용되지 않습니다. 사용하면 현재 스레드 이외의 스레드를 중단 할 수 있습니다. 일시 중단 된 스레드는 모든 모니터를 유지하며이 상태는 인터럽트 할 수 없으므로 교착 상태가 발생하기 쉽습니다.

object.wait()현재 스레드 를와 같은 "Not Runnable" 상태 로 보냅니다 sleep(). 스레드가 아닌 객체에서 대기가 호출됩니다. 이 개체를 "잠금 개체"라고합니다. lock.wait()호출 되기 전에 현재 스레드는 잠금 오브젝트에서 동기화해야합니다. wait() 그런 다음이 잠금을 해제하고 잠금과 연관된 "대기 목록"에 스레드를 추가합니다. 나중에 다른 스레드가 동일한 잠금 객체에서 동기화하고를 호출 할 수 있습니다 lock.notify(). 원래 대기 스레드를 깨 웁니다. 기본적으로, wait()/ notify()처럼 sleep()/ interrupt()만 활성 스레드 만 공유 잠금 개체, 잠자는 스레드에 대한 직접적인 포인터를 필요로하지 않는다.


14

대기와 수면은 서로 다른 두 가지입니다.

  • 에서 sleep()스레드가 지정된 시간 동안 작동을 멈 춥니 다.
  • 에서 wait()실 물체 존재 기다리는 기능까지 통지 일반적으로 다른 스레드에 의해, 작동하지.

그러나 잠자는 스레드를 중단 할 수 있습니다. 이 경우 wait ()가 중복되어 실제로 CPU 사이클을 낭비합니다 :-(
Geek

9
대기는 CPU주기를 낭비하지 않습니다.
피터 Štibraný

1
@ 피터-나는 그렇게 생각합니다. CPU 사이클 청크를 기다린 다음 OS가 CPU 사이클을 다른 스레드에 제공합니다. 나는 이것이 OS에 따라 다를 수 있다고 생각합니다.
Geek

3
CPU 사이클을 낭비하면 wait () 구현이 매우 좋지 않습니다. 대기 / 알림은 스레드 간 통신에 상당히 많이 사용됩니다.
Peter Štibraný

2
@Pacerier 두 구성은 다른 목적으로 사용됩니다. 쓰레드를 일정 시간 동안 sleep정지 시키려면, 다른 입력에서 입력이 나올 때까지 쓰레드를 멈추려 면 wait/ 를 사용하십시오 notify. interrupt스레드가 스레드의 작업 수행을 중지하고 종료해야한다는 신호를 보내는 방식으로 고안되었습니다. 그것은에 의해 처리됩니다 sleep, wait뿐만 아니라 (그리고 당신이 메서드를 호출하여 동일한 동작과 기능을 구현할 수있는 I / O 기능을 차단 Thread.interrupted()). 성능과 관련하여 기능은 일반적으로 설계된 목표에 맞게 최적화됩니다.
pqnet

11

sleep방법이며 Thread, wait한 방법이 Object있으므로 wait/notify(자바하여 공유 데이터를 동기화하는 방법이다 모니터 ), 그러나 sleep그 자체를 일시 정지 나사의 단순한 방법이다.


8

sleep () 은 몇 초 동안 또는 원하는 시간 동안 프로세스를 유지하는 데 사용되는 메소드이지만 wait () 메소드 스레드가 대기 상태가되고 notify ()를 호출 할 때까지 자동으로 돌아 오지 않습니다. notifyAll ().

가장 큰 차이점wait () 가 잠금 또는 모니터를 해제하는 반면 sleep ()은 대기 중 잠금 또는 모니터를 해제하지 않는다는 것입니다. 대기는 스레드 간 통신에 사용되는 반면 절전은 일반적으로 실행 일시 중지를 발생시키는 데 사용됩니다.

Thread.sleep () 은 현재 스레드를 일정 시간 동안 "실행할 수 없음"상태로 보냅니다. 스레드는 획득 한 모니터를 유지합니다. 즉, 스레드가 현재 동기화 된 블록 또는 메소드에있는 경우 다른 스레드가이 블록 또는 메소드를 입력 할 수 없습니다. 다른 스레드가 t.interrupt ()를 호출하면 휴면 스레드를 깨 웁니다. sleep은 정적 메소드이므로 항상 현재 스레드 (sleep 메소드를 실행중인 스레드)에 영향을 미칩니다. 일반적인 실수는 t.sleep ()을 호출하는 것입니다. 여기서 t는 다른 스레드입니다. 그럼에도 불구하고 t 스레드가 아닌 현재 스레드입니다.

object.wait () 는 현재 스레드를 sleep ()과 같은 "Not Runnable"상태로 보내지 만 비틀어 놓습니다. 스레드가 아닌 객체에서 대기가 호출됩니다. 이 개체를 "잠금 개체"라고합니다. lock.wait ()가 호출되기 전에 현재 스레드가 잠금 오브젝트에서 동기화되어야합니다. wait ()는이 잠금을 해제하고 잠금과 연관된 "대기 목록"에 스레드를 추가합니다. 나중에 다른 스레드가 동일한 잠금 개체에서 동기화하고 lock.notify ()를 호출 할 수 있습니다. 원래 대기 스레드를 깨 웁니다. 기본적으로 wait () / notify ()는 sleep () / interrupt ()와 유사하며 활성 스레드에만 휴면 스레드에 대한 직접 포인터가 필요하지 않고 공유 잠금 객체에만 필요합니다.

synchronized(LOCK) {   
   Thread.sleep(1000); // LOCK is held
}

synchronized(LOCK) {   
   LOCK.wait(); // LOCK is not held
}

위의 모든 포인트를 분류하십시오.

Call on:

  • wait () : 객체를 호출합니다. 현재 스레드는 잠금 오브젝트에서 동기화해야합니다.
  • sleep () : 스레드 호출; 항상 현재 실행중인 스레드.

Synchronized:

  • wait () : 여러 스레드를 동기화 할 때 동일한 Object에 하나씩 액세스합니다.
  • sleep () : 여러 스레드를 동기화 할 때 휴면 스레드의 휴면을 기다립니다.

Hold lock:

  • wait () : 다른 객체가 실행되도록 잠금을 해제합니다.
  • sleep () : 시간 초과가 지정되거나 누군가가 중단 된 경우 최소 t 회 동안 잠금 상태를 유지합니다.

Wake-up condition:

  • wait () : 객체에서 notify (), notifyAll ()을 호출 할 때까지
  • sleep () : 적어도 시간이 만료되거나 인터럽트 ()를 호출 할 때까지.

Usage:

  • sleep () : 시간 동기화 및;
  • wait () : 다중 스레드 동기화 용.

참조 : diff sleepandwait


6

간단히 말해서, wait is wait 다른 스레드가 당신을 호출 할 때까지 잠자는 동안 지정된 시간 동안 "다음 명령문을 실행하지 않습니다".

또한 sleep은 Thread 클래스에서 정적 메서드이며 스레드에서 작동하지만 wait ()는 Object 클래스에 있고 객체에서 호출됩니다.

다른 점은 일부 객체에서 대기를 호출하면 관련된 스레드가 객체를 동기화 한 다음 대기합니다. :)


1
왜 둘 다 필요합니까? 왜 sleep ()이 충분하지 않습니까?
Geek

2
알림은 스레드 간 통신에 사용됩니다. 대기를 호출하려면 객체가 필요하고 동기화 한 다음 대기를 호출하십시오. 알림을 받으려면 동일한 객체에서 동기화 하고 notify를 호출 하기 위해 다른 스레드가 필요합니다 .
피터 Štibraný

6

waitsleep방법은 매우 다릅니다 :

  • sleep "깨어 난"방법이 없습니다
  • 반면 wait"깨어 업"대기 기간 동안, 다른 스레드의 호출에 의해하는 방법이있다 notify또는 notifyAll.

그것에 대해 생각해 보니, 이름은 그 점에서 혼란 스럽습니다. 그러나 sleep표준 이름이고 wait등이다 WaitForSingleObject또는 WaitForMultipleObjects윈의 API에.


3
그러나 우리는 잠을 방해 할 수 없습니까? 그래서 그 수면 / 인터럽트와 대기 / 알림의 차이점은 무엇입니까?
Pacerier

2
잠자는 사람을 방해 할 수 있지만 기다리는 사람에게만 알릴 수 있습니다. 스레드는 동일합니다.
Rishi

5

이 게시물에서 : http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/

wait () 메소드.

1) wait () 메소드를 호출하는 스레드는 보유한 잠금을 해제합니다.

2) 다른 스레드가 동일한 잠금에서 notify () 또는 notifyAll () 메소드를 호출하면 스레드가 잠금을 다시 얻습니다.

3) wait () 메소드는 동기화 된 블록 내에서 호출되어야합니다.

4) wait () 메소드는 항상 객체에서 호출됩니다.

5) 대기중인 스레드는 notify () 또는 notifyAll () 메소드를 호출하여 다른 스레드에 의해 깨어날 수 있습니다.

6) wait () 메소드를 호출하려면 스레드에 객체 잠금이 있어야합니다.

sleep () 메소드

1) sleep () 메소드를 호출하는 스레드는 보유하고있는 잠금을 해제하지 않습니다.

2) sleep () 메소드는 동기화 된 블록 내부 또는 외부에서 호출 될 수 있습니다.

3) sleep () 메소드는 항상 스레드에서 호출됩니다.

4) 잠자는 실을 다른 실로 깨울 수 없습니다. 그렇게하면 스레드가 InterruptedException을 throw합니다.

5) sleep () 메소드를 호출하기 위해 스레드는 객체 잠금을 가질 필요가 없습니다.


4
  1. wait()Object클래스 의 방법입니다 . 클래스
    sleep()의 방법입니다 Thread.

  2. sleep()스레드가 sleepx 밀리 초 동안 상태 로 전환되도록 합니다.
    스레드가 휴면 상태가 될 때 it doesn’t release the lock.

  3. wait()스레드가 잠금을 해제 할 수 있도록합니다 goes to suspended state.
    이 스레드는 동일한 객체에 대해 notify()또는 notifAll()메소드가 호출 될 때 활성화됩니다 .


4

수면 / 인터럽트와 대기 / 알림의 잠재적 인 큰 차이점 중 하나는

필요하지 않은 예외를 생성하는 것은 비효율적입니다. 스레드가 높은 속도로 서로 통신하는 경우 인터럽트를 항상 호출하면 많은 예외가 발생합니다. 이는 총 CPU 낭비입니다.


+1, 구현 의 내부 에 논쟁하는 것이 성능 분석과 더 관련이있을 수 있지만 실제로는 유효한 포인트입니다 .
Pacerier

다시 말해, 예외를 생성하는 오버 헤드는 시스템이 구현하는 오버 헤드보다 훨씬 작을 수 있습니다.
Pacerier

3

당신이 맞습니다-Sleep ()은 스레드가 "슬립"하게하고 CPU는 다른 스레드 (컨텍스트 전환이라고도 함)를 처리하지만 CPU가 현재 스레드를 처리하는 CPU를 계속 유지한다고 생각합니다.

우리는 다른 사람이 CPU를 사용하지 않는 동안 CPU를 사용하는 것이 합리적으로 보일 수 있지만 실제로는 컨텍스트 전환에 오버 헤드가 있습니다-수면 시간에 따라 CPU 사이클이 더 비쌀 수 있습니다 스레드를 단순히 몇 ms 동안 아무것도하지 않는 것보다 스레드를 전환하는 것입니다.

또한 sleep은 컨텍스트 전환을 강제합니다.

또한 일반적으로 컨텍스트 전환을 제어 할 수 없습니다. 대기 중 OS가 다른 스레드를 처리하도록 선택할 수 있습니다 (더 이상 대기 할 경우).


4
wait ()는 CPU가 현재 스레드를 처리하지 않습니다. javamex.com/tutorials/threads/context_switch.shtml 과 같이 컨텍스트 전환을 유발한다는 점에서 절전과 같습니다 . 나는 스택 오버 플로우와 관련하여 반년을 요구해 왔으며 대기 / 알림과 수면 / 인터럽트의 차이점을 아는 사람이없는 것 같습니다.
Pacerier

수면은 현재 스레드를 처리하는 데 CPU를 유지하지 않지만 CPU는 수면을 끝내는 순간을 추적해야하기 때문에 CPU에 약간의 부담이됩니다. 대기중인 "알림"과 같은 외부 트리거가 없습니다. 아니?
블라디미르 나보코프

@VladimirNabokov, 외부 트리거는 interrupt입니다. 종료 시간은 n입니다 wait(n). ¶¶ 지금은 8 년이 지났지 만 아직 아무도 답이 없습니다!
Pacerier

3

방법은 다른 것들에 사용됩니다.

Thread.sleep(5000);   // Wait until the time has passed.

Object.wait();        // Wait until some other thread tells me to wake up.

Thread.sleep를 (N)을 할 수 있습니다 중단 될 수 있지만,되는 Object.wait ()가 있어야합니다 통보. 그것은 최대 대기 시간 지정 가능 : Object.wait(5000)이 사용 가능한 것, 그래서 wait어,로를, sleep하지만 당신은 잠금 귀찮게해야합니다.

두 방법 모두 절전 / 대기 중에 CPU를 사용하지 않습니다.

메소드는 유사한 구성을 사용하지만 동일한 방식으로 네이티브 코드를 사용하여 구현됩니다.

자신을 찾으십시오. 기본 메소드의 소스 코드를 사용할 수 있습니까? 파일 /src/share/vm/prims/jvm.cpp은 시작점입니다 ...


Thread.sleep 타이밍도 무한으로 설정할 수 있습니다. Object.wait 타이밍도 한정적으로 설정할 수 있습니다. 이 답변은 왜 같은 일을하는 망치 2 개가 필요한지 설명하지 않습니다.
Pacerier

Thread.sleep(big_num) 중단 되어야 합니다. 통보 Object.wait(small_num) 받을 수 있습니다.
Pacerier

3

여기에서 wait ()는 다른 Thread에 의해 알릴 때까지 대기 상태에 있지만 sleep ()이 어느 정도 시간이 걸리는 곳입니다.


3

Wait ()와 sleep ()의 차이점?

Thread.sleep () 일단 작업이 완료되면 모든 사람에게 잠금을 해제합니다. 잠금 장치가 해제 될 때까지

  Sleep() take the key, its never release the key to anyone, when its work completed then only its release then only take the key waiting stage threads.

Object.wait () 대기 단계로 이동하면 키를 해제하고 매개 변수를 기반으로 몇 초 동안 대기합니다.

예를 들어 :

당신은 당신의 오른손에 커피를 가지고 있습니다, 당신은 같은 손의 다른 사람을 데려 갈 수 있습니다. 또한. 이것은 sleep ()입니다. 당신이 일하지 않은 시간, 당신은 잠을 자고 있습니다. 여기도 마찬가지입니다.

기다림(). 당신이 내려 놓고 기다리는 동안 또 다른 의미를 취할 때, 그것은 기다립니다

당신은 한 번에 둘 이상을 재생할 수없는 플레이어와 같은 영화 또는 시스템에서 아무것도 재생합니다. 즉, 닫고 다른 사람의 영화 나 노래를 선택하면 대기라고합니다.


3

wait잠금을 해제 sleep하지 않습니다. 대기 상태의 스레드는 notify또는 notifyAll호출 되는 즉시 깨울 수 있습니다. 그러나 sleep스레드가 잠금을 유지하는 경우 잠자기 시간이 끝나면 자격이 부여됩니다.


따라서 스레드가 10 초 동안 잠자고 중단 된 예외가 발생하면 ????
Geek

@Geek An InterruptedException은 Javadoc에서 말하는 것처럼 던져집니다.
user207421

@EJP : 당신은 sun.java.com 포럼에 있었던 동일한 EJP입니까? Atleast 님의 점수는 동일하게 제안합니다 :-)
Geek

2

sleep()메소드는 현재 스레드가 지정된 시간 동안 실행 상태에서 블록 상태로 이동합니다. 현재 스레드에 객체 잠금이있는 경우 계속 유지하므로 다른 스레드가 해당 클래스 객체에서 동기화 된 메서드를 실행할 수 없습니다.

wait() 메소드는 현재 스레드가 지정된 시간 동안 또는 통지 할 때까지 블록 상태가되지만이 경우 스레드는 오브젝트 잠금을 해제합니다 (이는 다른 스레드가 호출 오브젝트의 동기화 된 메소드를 실행할 수 있음을 의미합니다).


2

필자의 의견으로는 두 메커니즘의 주요 차이점은 휴면 / 인터럽트가 스레드를 처리하는 가장 기본적인 방법이며, 대기 / 알림은 스레드 상호 통신을보다 쉽게 ​​수행 할 수 있도록하는 추상화라는 점입니다. 이것은 수면 / 인터럽트가 무엇이든 할 수 있지만이 특정 작업은 더 어렵다는 것을 의미합니다.

대기 / 알림이 더 적합한 이유는 무엇입니까? 다음은 몇 가지 개인적인 고려 사항입니다.

  1. 중앙 집중화를 시행합니다. 단일 공유 객체를 사용하여 스레드 그룹 간의 통신을 조정할 수 있습니다. 이것은 작업을 많이 단순화합니다.

  2. 동기화를 시행합니다. 프로그래머가 동기화 된 블록에서 대기 / 알림을 위해 호출을 랩핑하기 때문입니다.

  3. 스레드 원점 및 번호와 무관합니다. 이 방법을 사용하면 다른 스레드를 편집하거나 기존 스레드를 추적하지 않고도 스레드를 임의로 추가 할 수 있습니다. 휴면 / 인터럽트를 사용한 경우 먼저 휴면 스레드에 대한 참조를 유지 한 다음 하나씩 수작업으로 중단해야합니다.

실생활의 예로는 고전 식당과 직원들이 의사 소통을하는 데 사용하는 방법이 있습니다. 웨이터는 고객의 요청을 중앙 장소 (코크 보드, 테이블 등)에 남겨두고, 종을 울리면 부엌의 일꾼들이 그러한 요청을받습니다. 코스 준비가 완료되면 주방 직원이 종을 다시 울려 웨이터가 인식하고 고객에게 가져갑니다.


2

수면에 대한 예는 잠금을 해제하지 않고 대기는 해제합니다.

여기에는 두 가지 클래스가 있습니다.

  1. Main : 메인 메소드와 두 개의 스레드를 포함합니다.
  2. Singleton : 두 개의 정적 메소드 getInstance () 및 getInstance (boolean isWait)가있는 싱글 톤 클래스입니다.

    public class Main {
    
    private static Singleton singletonA = null;
    private static Singleton singletonB = null;
    
    public static void main(String[] args) throws InterruptedException {
    
    Thread threadA = new Thread() {
        @Override
        public void run() {
    
            singletonA = Singleton.getInstance(true);
    
        }
    };
    
    Thread threadB = new Thread() {
        @Override
        public void run() {
            singletonB = Singleton.getInstance();
    
            while (singletonA == null) {
                System.out.println("SingletonA still null");
            }
    
            if (singletonA == singletonB) {
                System.out.println("Both singleton are same");
            } else {
                System.out.println("Both singleton are not same");
            }
    
        }
    };
    
    threadA.start();
    threadB.start();
    
     }
    }

public class Singleton {

    private static Singleton _instance;

    public static Singleton getInstance() {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null)
                _instance = new Singleton();
        }
    }
    return _instance;

}

public static Singleton getInstance(boolean isWait) {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null) {
                if (isWait) {
                    try {
                        // Singleton.class.wait(500);//Using wait
                        Thread.sleep(500);// Using Sleep
                        System.out.println("_instance :"
                                + String.valueOf(_instance));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                _instance = new Singleton();
            }
        }
    }
    return _instance;

 }
}

이제이 예제를 실행하면 출력이 아래에 표시됩니다.

_instance :null
Both singleton are same

여기서 threadA와 threadB로 작성된 싱글 톤 인스턴스는 동일합니다. threadA가 잠금을 해제 할 때까지 threadB가 외부에서 대기 중임을 의미합니다.

이제 Thread.sleep (500); 메소드 및 주석 해제 Singleton.class.wait (500); . Singleton.class.wait (500) 때문에 여기에; threadA 메소드는 모든 획득 잠금을 해제하고 "Non Runnable"상태로 이동하며 threadB는 동기화 된 블록에 들어가도록 변경됩니다.

이제 다시 실행하십시오.

SingletonA still null
SingletonA still null
SingletonA still null
_instance :com.omt.sleepwait.Singleton@10c042ab
SingletonA still null
SingletonA still null
SingletonA still null
Both singleton are not same

threadA와 threadB에 의해 작성된 Singleton 인스턴스는 threadB가 동기화 된 블록에 들어가도록 변경되어 500 밀리 초 후에 threadA가 마지막 위치에서 시작하여 하나 이상의 Singleton 객체를 생성했기 때문에 동일하지 않습니다.


2

동기화 된 블록에서 호출되어야합니다. wait() 메소드는 항상 동기화 된 블록에서 호출됩니다. 즉, wait()메소드는 호출 된 오브젝트 전에 오브젝트 모니터를 잠 가야합니다 . 그러나 sleep()메소드는 외부 동기화 블록에서 호출 할 수 있습니다. 즉 sleep()메소드에는 객체 모니터가 필요하지 않습니다.

IllegalMonitorStateException : 런타임시 발생하는 wait()것보다 객체 잠금을 획득하지 않고 메소드를 호출하는 경우IllegalMonitorStateExceptionsleep() 방법은 결코 같은 예외가 발생하지 않습니다.

어떤 클래스에 속합니까 : wait() method는 java.lang.Object클래스에 sleep()속 하지만 method는 java.lang.Thread클래스에 속합니다 .

객체 또는 스레드에서 호출 : wait() 메소드는 객체에서 호출되지만 sleep()메소드는 객체가 아닌 스레드에서 호출됩니다.

스레드 상태 :wait() 객체에서 메소드가 호출 되면 객체의 모니터를 보유한 스레드가 실행 상태에서 대기 상태로 전환되고 해당 객체에서 notify()또는 notifyAll()메소드가 호출 된 경우에만 실행 가능한 상태로 돌아갈 수 있습니다 . 그리고 나중에 스레드 스케줄러는 해당 스레드가 실행 가능 상태에서 실행 상태로 이동하도록 스케줄합니다. sleep()스레드에서 호출 되면 실행 상태에서 대기 상태로 전환되고 절전 시간이되면 실행 가능 상태로 돌아갈 수 있습니다.

동기화 된 블록에서 호출 된 경우 :wait() 메소드가 호출 되면 스레드가 오브젝트 잠금을 벗어납니다. 그러나 sleep()동기화 된 블록이나 메소드 스레드에서 호출 될 때 메소드는 객체 잠금을 유지하지 않습니다.

추가 참조


아마 그보다 더 좋은 참조 URL입니다.
Drew

2

wait () 메소드의 Oracle 문서 페이지에서 Object:

public final void wait()
  1. 다른 스레드 가이 객체 의 notify()메서드 또는 notifyAll()메서드를 호출 할 때까지 현재 스레드가 대기 하도록합니다. 즉,이 메소드는 단순히 call을 수행하는 것처럼 정확하게 작동합니다 wait(0).
  2. 현재 스레드는이 객체의 모니터를 소유해야합니다. 스레드는이 모니터의 소유권을 해제하고 다른 스레드가이 개체의 모니터에서 대기중인 스레드에게 깨울 때까지 기다립니다.
  3. 인터럽트 및 가짜 웨이크 업 가능
  4. 이 메소드는이 객체의 모니터 소유자 인 스레드에 의해서만 호출되어야합니다.

이 방법은

  1. IllegalMonitorStateException -현재 스레드가 객체 모니터의 소유자가 아닌 경우

  2. InterruptedException-현재 스레드가 알림을 대기하기 전이나 기다리는 동안 스레드가 현재 스레드를 중단 한 경우 이 예외가 발생하면 현재 스레드의 중단 된 상태가 지워집니다.

클래스의 sleep () 메소드에 대한 Oracle 문서 페이지에서 Thread:

public static void sleep(long millis)
  1. 시스템 타이머 및 스케줄러의 정밀도 및 정확성에 따라 현재 실행중인 스레드가 지정된 시간 (밀리 초) 동안 휴면 (일시적으로 실행 중단)되도록합니다.
  2. 스레드는 모니터의 소유권을 잃지 않습니다.

이 방법은 다음을 발생시킵니다.

  1. IllegalArgumentException -밀리 값이 음수 인 경우

  2. InterruptedException-스레드가 현재 스레드를 중단 한 경우 이 예외가 발생하면 현재 스레드의 중단 된 상태가 지워집니다.

다른 주요 차이점 :

wait()정적 메소드 sleep()(클래스 메소드) 와 달리 비 정적 메소드 (인스턴스 메소드)입니다.


1

wait()반면 동기화 방법 안에 부여 sleep()하기 때문에 비 동기화 방법 안에 부여 wait()방법은 개체의 잠금을 해제하지만 sleep()또는 yield()해제하지 lock().


sleep()synchronized블록이나 메소드 안에있을 수 있습니다 . 대답은 아무것도 설명하지 않습니다.
user207421

1
  • 이 메소드 wait(1000)는 현재 스레드가 최대 1 초 동안 휴면 상태가 되도록합니다 .
    • 스레드가 notify()또는notifyAll() 메소드 호출을 수신하면 1 초 미만으로 휴면 상태가 될 수 있습니다.
  • 호출 sleep(1000)하면 현재 스레드가 정확히 1 초 동안 휴면 상태가 됩니다 .
    • 또한 잠자는 스레드는 어떤 리소스도 잠그지 않습니다 . 그러나 대기 스레드가 수행합니다.

1
sleep(1000)정확히 1 초 동안 잠자기 보장하지 않습니다. 이전에 중단되었을 수 있습니다.
Lucio

1
이 게시물은 너무 혼란 스럽습니다. 이 스레드의 다른 모든 게시물은 잠자는 스레드가 잠금을 유지하고 대기 스레드는 잠금을 유지한다고 말합니다. 마찬가지로 다이어그램이있는 게시물은 notify () 호출 수면 스레드를 깨우지 만 다른 게시물 (및 스레드 상태 다이어그램)은 인터럽트 () 또는 시간 초과 기간만이 수행한다는 것을 암시합니다. 방금 실제로 Java 동시성 사본을 주문했습니다. 오래 전에 읽었어야 할 것입니다!
berimbolo

1

실제로,이 모든 것은 Java 문서에 명확하게 설명되어 있습니다 (그러나 나는 대답을 읽은 후에 만 ​​이것을 깨달았습니다).

http://docs.oracle.com/javase/8/docs/api/index.html :

wait ()-현재 스레드는이 객체의 모니터를 소유해야합니다. 스레드는이 모니터의 소유권을 해제하고 다른 스레드가이 객체의 모니터에서 대기중인 스레드가 notify 메소드 또는 notifyAll 메소드에 대한 호출을 통해 깨어나도록 알릴 때까지 기다립니다. 그런 다음 스레드는 모니터 소유권을 다시 얻을 수있을 때까지 기다렸다가 실행을 다시 시작합니다.

sleep ()-시스템 타이머 및 스케줄러의 정밀도 및 정확성에 따라 현재 실행중인 스레드가 지정된 시간 (밀리 초) 동안 휴면 (일시적으로 실행 중단)되도록합니다. 스레드는 모니터의 소유권을 잃지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.