Skillnaden mellan vänta och sova i Java

1. Översikt

I den här korta artikeln kommer vi att titta på standardmetoderna sleep () och wait () i Java-kärnan och förstå skillnaderna och likheterna mellan dem.

2. Allmänna skillnader mellan väntan och sömnen

Enkelt uttryckt, vänta () är en instansmetod som används för trådsynkronisering.

Det kan anropas på vilket objekt som helst, som det definieras direkt på java.lang.Object, men det kan bara anropas från ett synkroniserat block . Det släpper låset på objektet så att en annan tråd kan hoppa in och få ett lås.

Å andra sidan är Thread.sleep () en statisk metod som kan anropas från vilket sammanhang som helst. Thread.sleep () pausar den aktuella tråden och släpper inte några låser.

Här är en mycket förenklad inledande titt på dessa två kärn-API: er i aktion:

private static Object LOCK = new Object(); private static void sleepWaitExamples() throws InterruptedException { Thread.sleep(1000); System.out.println( "Thread '" + Thread.currentThread().getName() + "' is woken after sleeping for 1 second"); synchronized (LOCK) { LOCK.wait(1000); System.out.println("Object '" + LOCK + "' is woken after" + " waiting for 1 second"); } } 

Att köra det här exemplet ger följande utdata:

Tråden "huvud" väcks efter att ha sovit i 1 sekund

Objektet '[email protected]' väcks efter att ha väntat i en sekund

3. Vakna Vänta och sova

När vi använder sleep () -metoden startar en tråd efter ett angivet tidsintervall, såvida det inte avbryts.

För att vänta () är väckningsprocessen lite mer komplicerad. Vi kan väcka tråden genom att anropa antingen notify () eller notifyAll () -metoderna på skärmen som väntar på.

Använd notifyAll () istället för notify () när du vill väcka alla trådar som är i vänteläge. Liknande sätt som den vänta () metoden i sig, meddela () , och notifyAll () måste anropas från den synkroniserade sammanhang.

Så här kan du till exempel vänta :

synchronized (b) { while (b.sum == 0) { System.out.println("Waiting for ThreadB to complete..."); b.wait(); } System.out.println("ThreadB has completed. " + "Sum from that thread is: " + b.sum); }

Och så här är hur en annan tråd sedan kan väcka den väntande tråden - genom att ringa notify () på skärmen :

int sum; @Override public void run() { synchronized (this) { int i = 0; while (i < 100000) { sum += i; i++; } notify(); } }

Att köra det här exemplet ger följande utdata:

Väntar på att ThreadB ska slutföras ...

ThreadB har slutförts. Summan från den tråden är: 704982704

4. Slutsats

Detta är en snabb primer till semantiken att vänta och sova i Java.

I allmänhet bör vi använda sömn () för att styra exekveringstiden för en tråd och vänta () på synkronisering med flera trådar. Naturligtvis finns det mycket mer att utforska - efter att ha förstått grunderna väl.

Som alltid kan du kolla in exemplen i den här artikeln på GitHub.