Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use wait-notify method correctly in Java

2025-01-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article introduces the relevant knowledge of "how to correctly use the wait-notify method in Java". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

1. The difference between sleep (long n) and wait (long n)

(1) sleep is the Thread method, while wait is the Object method.

(2) sleep does not need to be used in conjunction with synchronized, but wait needs to be used with synchronized.

(3) sleep will not release the object lock while sleeping, but wait will release the object lock while waiting

(4) their status TIMED_WAITING

@ Slf4jpublic class Test1 {private static final Object lock = new Object (); public static void main (String [] args) throws InterruptedException {new Thread (()-> {synchronized (lock) {log.debug ("T1 thread acquires lock...."); try {Thread.sleep (20000) } catch (InterruptedException e) {e.printStackTrace ();}, "T1") .start (); / / wait 1 s for thread to execute T1 thread Thread.sleep (1000) / / the lock cannot be acquired because the T1 thread does not release the lock synchronized (lock) {log.debug ("the main thread wants to acquire the lock.");}

Result of executing the sleep () method: the main thread does not acquire a lock during thread T1 sleep

10 _ a lock.

@ Slf4jpublic class Test1 {private static final Object lock = new Object (); public static void main (String [] args) throws InterruptedException {new Thread (()-> {synchronized (lock) {log.debug ("T1 thread acquires lock...."); try {lock.wait () } catch (InterruptedException e) {e.printStackTrace ();}, "T1") .start (); / / wait 1 s for thread to execute T1 thread Thread.sleep (1000) / / the lock cannot be acquired because the T1 thread does not release the lock synchronized (lock) {log.debug ("the main thread wants to acquire the lock.");}

The result of executing the wait () method: thread T1 waits for 20s, while online program T1 waits, the main thread acquires the lock

10RV 36RV 22.723 [T1] DEBUG com.example.test.Test1-T1 thread acquires the lock....

10RV 36RV 23.721 [main] DEBUG com.example.test.Test1-the main thread wants to acquire the lock.

two。 Correct use of wait-notify method [while (condition) + wait]

Scene: several children want to enter the room and use the abacus (CPU) to calculate, so Lao Wang (operating system) uses a synchronized so that only one child can enter the room at a time, so they line up to enter the room.

(1) Xiaonan is the first to get the lock and enter the room, but because the conditions are not satisfied (no smoke can not work), Xiaonan can not continue to calculate, but if Xiaonan keeps occupying the lock, others will have to block all the time, and the efficiency is too low.

(2) so Lao Wang opened a lounge (call wait method) and asked Xiao Nan to wait in the lounge (WaitSet). At this time, the lock was released, and others could be randomly arranged by Lao Wang to enter the room.

(3) until Little M delivers the cigarette, shout [your cigarette has arrived] (call the notify method)

(4) Xiao Nan can then leave the lounge and re-enter the competitive lock queue.

Let's see how to correctly implement this scenario.

2.1 question 1@Slf4jpublic class Test2 {private static final Object room = new Object (); / / whether there is a cigarette, there is no private static boolean hasCigarette = false; public static void main (String [] args) throws InterruptedException {new Thread (()-> {synchronized (room) {log.debug ("do you have a cigarette? [{}] ", hasCigarette); if (! hasCigarette) {log.debug (" No smoke, take a break! ") ; try {Thread.sleep (2000);} catch (InterruptedException e) {e.printStackTrace ();}} log.debug ("do you have a cigarette? [{}] ", hasCigarette); if (hasCigarette) {log.debug (" smoke, [{}], you can start work ", hasCigarette);}," Xiaonan "). Start (); / / the other five threads also want to acquire the lock to enter the room for (int item0) I {synchronized (room) {log.debug ("ready to work");}}, "others") .start ();} / the main thread waits for 1s Thread.sleep (1000) / / because the small southern thread uses the sleep () method, he does not release the lock during sleep, and the cigarette messenger cannot get the lock to enter the room to send cigarettes new Thread (()-> {synchronized (room) {hasCigarette = true;}}, "cigarette delivery"). Start ();}}

Execution result:

11PUR 10RV 50.556 [Xiao Nan] DEBUG com.example.test.Test2-do you have a cigarette? [false]

11PUR 10WR 50.565 [Xiao Nan] DEBUG com.example.test.Test2-No smoke, take a break!

11PUR 10RU 52.565 [Xiao Nan] DEBUG com.example.test.Test2-do you have a cigarette? [false]

11RV 10RV 52.565 [others] DEBUG com.example.test.Test2-ready to go to work

11RV 10RV 52.565 [others] DEBUG com.example.test.Test2-ready to go to work

11RV 10RV 52.565 [others] DEBUG com.example.test.Test2-ready to go to work

11RV 10RV 52.565 [others] DEBUG com.example.test.Test2-ready to go to work

11RV 10RV 52.565 [others] DEBUG com.example.test.Test2-ready to go to work

(1) the Xiaonan thread does not release the lock during sleep, so other threads cannot acquire the lock to enter the room, and the cigarette sending thread cannot deliver cigarettes.

(2) other working threads have to be blocked all the time, and the efficiency is too low.

To solve the above problems, you need to use the wait-notify mechanism

2.2 question 2@Slf4jpublic class Test2 {private static final Object room = new Object (); / / whether there is a cigarette, there is no private static boolean hasCigarette = false; public static void main (String [] args) throws InterruptedException {new Thread (()-> {synchronized (room) {log.debug ("do you have a cigarette? [{}] ", hasCigarette); if (! hasCigarette) {log.debug (" No smoke, take a break! ") ; try {room.wait ();} catch (InterruptedException e) {e.printStackTrace ();}} log.debug ("do you have a cigarette? [{}] ", hasCigarette); if (hasCigarette) {log.debug (" smoke, [{}], you can start work ", hasCigarette);}," Xiaonan "). Start (); / / the other five threads also want to acquire the lock to enter the room for (int item0) I {synchronized (room) {log.debug ("ready to work");}}, "others") .start ();} / the main thread waits for 1s Thread.sleep (1000) / / to wake up the sleeping southern thread new Thread (()-> {synchronized (room) {hasCigarette = true; room.notify ();}}, "cigarette delivery") .cigarette ();}}

Execution result:

11RU 21RU 36.775 [Xiao Nan] DEBUG com.example.test.Test2-do you have a cigarette? [false]

11PUR 21VR 36.780 [Xiaonan] DEBUG com.example.test.Test2-No smoke, take a break!

11RV 21RV 36.780 [others] DEBUG com.example.test.Test2-Let's get to work

11RV 21RV 36.780 [others] DEBUG com.example.test.Test2-Let's get to work

11RV 21RV 36.781 [others] DEBUG com.example.test.Test2-Let's get to work

11RV 21RV 36.781 [others] DEBUG com.example.test.Test2-Let's get to work

11RV 21RV 36.781 [others] DEBUG com.example.test.Test2-Let's get to work

11MU 21UR 37.773 [Xiao Nan] DEBUG com.example.test.Test2-do you have a cigarette? [true]

11MU 21GV 37.774 [Xiao Nan] DEBUG com.example.test.Test2-smoke, [true], you can get to work.

Solved the problem of blocking other threads, but what if other threads are also waiting? That is to say, Xiao Nan is not the only thread waiting, so will it be wrong to wake up?

2.3 question 3@Slf4jpublic class Test2 {private static final Object room = new Object (); / / whether there is a cigarette. By default, there is no private static boolean hasCigarette = false; / / whether there is takeout, and there is no static boolean hasTakeout = false; public static void main (String [] args) throws InterruptedException {new Thread (()-> {synchronized (room) {log.debug ("do you have a cigarette? [{}] ", hasCigarette); if (! hasCigarette) {log.debug (" No smoke, take a break! ") ; try {room.wait ();} catch (InterruptedException e) {e.printStackTrace ();}} log.debug ("do you have a cigarette? [{}] ", hasCigarette); if (hasCigarette) {log.debug (" smoke, [{}], you can start work ", hasCigarette);} else {log.debug (" didn't make it. ");}," Xiaonan "). Start () New Thread (()-> {synchronized (room) {log.debug ("do you have takeout? [{}] ", hasTakeout); if (! hasTakeout) {log.debug (" No takeout, take a break! ") ; try {room.wait ();} catch (InterruptedException e) {e.printStackTrace ();}} log.debug ("do you have takeout? [{}] ", hasTakeout); if (hasTakeout) {log.debug (" takeout, [{}], you can start work ", hasTakeout);} else {log.debug (" didn't make it. ");}," little girl "). Start () / / the main thread waits for 1s Thread.sleep (1000); new Thread (()-> {synchronized (room) {hasTakeout = true; log.debug); room.notify ();}}, "delivery" .start ();}}

Executive result: the delivery man was supposed to wake up the little girl, but woke Xiao Nan up.

11PUR 31RV 50.989 [Xiao Nan] DEBUG com.example.test.Test2-do you have a cigarette? [false]

11PUR 31RV 50.994 [Xiao Nan] DEBUG com.example.test.Test2-No smoke, take a break!

11PUR 31RV 50.994 [daughter] DEBUG com.example.test.Test2-do you have takeout? [false]

11PUR 31RV 50.994 [daughter] DEBUG com.example.test.Test2-No takeout, let's take a break!

11 31 51.987 [delivery] DEBUG com.example.test.Test2-takeout has arrived.

11PUR 31RV 51.988 [Xiao Nan] DEBUG com.example.test.Test2-do you have a cigarette? [false]

11PUR 31WR 51.988 [Xiao Nan] DEBUG com.example.test.Test2-didn't finish the job.

Notify can only wake up a thread in WaitSet at random. If other threads are also waiting, it may not wake up the correct thread, which is called false wake-up.

2.4 question 4

Solution: change to notifyAll

New Thread (()-> {synchronized (room) {hasTakeout = true; log.debug ("takeout to...."); room.notifyAll ();}, "delivery" .start ()

Execution result:

11MU 34MU 24.789 [Xiao Nan] DEBUG com.example.test.Test2-do you have a cigarette? [false]

11MU 34MU 24.798 [Xiao Nan] DEBUG com.example.test.Test2-No smoke, let's take a break!

11MU 34MU 24.798 [daughter] DEBUG com.example.test.Test2-do you have takeout? [false]

11MU 34DV 24.802 [daughter] DEBUG com.example.test.Test2-No takeout, let's take a break!

11MU 34Rd 25.794 [delivery] DEBUG com.example.test.Test2-takeout has arrived.

11MU 34Rd 25.794 [daughter] DEBUG com.example.test.Test2-do you have takeout? [true]

11MU 34RV 25.794 [daughter] DEBUG com.example.test.Test2-there is takeout, [true], you can start work.

11MU 34MU 25.794 [Xiao Nan] DEBUG com.example.test.Test2-do you have a cigarette? [false]

11MU 34Rd 25.795 [Xiao Nan] DEBUG com.example.test.Test2-didn't finish the job.

From the results, we can see that the little girl did the work, but Xiao Nan didn't. Since the cigarette delivery man has not arrived, Xiao Nan should continue to wait until the cigarette delivery man comes to work.

Using notifyAll only solves the wake-up problem of a thread, but there is only one chance to judge with if + wait. Once the condition is not established, there is no chance to rejudge.

2.5 final result @ Slf4jpublic class Test2 {private static final Object room = new Object (); / / whether there is a cigarette, there is no private static boolean hasCigarette = false; / / whether there is takeout by default, and there is no static boolean hasTakeout = false; public static void main (String [] args) throws InterruptedException {new Thread (()-> {synchronized (room) {log.debug ("do you have a cigarette? [{}] ", hasCigarette); while (! hasCigarette) {log.debug (" No smoke, take a break! ") ; try {room.wait ();} catch (InterruptedException e) {e.printStackTrace ();}} log.debug ("do you have a cigarette? [{}] ", hasCigarette); if (hasCigarette) {log.debug (" smoke, [{}], you can start work ", hasCigarette);} else {log.debug (" didn't make it. ");}," Xiaonan "). Start () New Thread (()-> {synchronized (room) {log.debug ("do you have takeout? [{}] ", hasTakeout); if (! hasTakeout) {log.debug (" No takeout, take a break! ") ; try {room.wait ();} catch (InterruptedException e) {e.printStackTrace ();}} log.debug ("do you have takeout? [{}] ", hasTakeout); if (hasTakeout) {log.debug (" takeout, [{}], you can start work ", hasTakeout);} else {log.debug (" didn't make it. ");}," little girl "). Start () / / the main thread waits for 1s Thread.sleep (1000); / / the cigarette sender wakes up the sleeping Little Southern thread new Thread (()-> {synchronized (room) {hasTakeout = true; log.debug ("takeout arrived...."); room.notifyAll () }}, "takeout"). Start ();}} @ Slf4jpublic class Test2 {private static final Object room = new Object (); / / whether there is a cigarette, there is no private static boolean hasCigarette = false; / / whether there is takeout, and there is no static boolean hasTakeout = false by default Public static void main (String [] args) throws InterruptedException {new Thread (()-> {synchronized (room) {log.debug ("do you have a cigarette? [{}] ", hasCigarette); while (! hasCigarette) {log.debug (" No smoke, take a break! ") ; try {room.wait ();} catch (InterruptedException e) {e.printStackTrace ();}} log.debug ("do you have a cigarette? [{}] ", hasCigarette); if (hasCigarette) {log.debug (" smoke, [{}], you can start work ", hasCigarette);} else {log.debug (" didn't make it. ");}," Xiaonan "). Start () New Thread (()-> {synchronized (room) {log.debug ("do you have takeout? [{}] ", hasTakeout); if (! hasTakeout) {log.debug (" No takeout, take a break! ") ; try {room.wait ();} catch (InterruptedException e) {e.printStackTrace ();}} log.debug ("do you have takeout? [{}] ", hasTakeout); if (hasTakeout) {log.debug (" takeout, [{}], you can start work ", hasTakeout);} else {log.debug (" didn't make it. ");}," little girl "). Start () / / the main thread waits for 1s Thread.sleep (1000); / / the cigarette sender wakes up the sleeping Little Southern thread new Thread (()-> {synchronized (room) {hasTakeout = true; log.debug ("takeout arrived...."); room.notifyAll () }}, "takeout"). Start ();}}

Execution result: when there is no smoke, the Xiaonan thread continues to wait, waiting for the next time it is judged that there is smoke before working

11RV 38RU 36.206 [Xiao Nan] DEBUG com.example.test.Test2-do you have a cigarette? [false]

11PUR 38RV 36.212 [Xiao Nan] DEBUG com.example.test.Test2-No smoke, take a break!

11PUR 38RV 36.212 [daughter] DEBUG com.example.test.Test2-do you have takeout? [false]

11RV 38Rd 36.212 [daughter] DEBUG com.example.test.Test2-No takeout, let's take a break!

11PUR 38GV 37.205 [delivery] DEBUG com.example.test.Test2-takeout has arrived.

11PUR 38PUR 37.205 [daughter] DEBUG com.example.test.Test2-do you have takeout? [true]

11PUR 38GV 37.205 [daughter] DEBUG com.example.test.Test2-takeout, [true], ready to go to work

11PUR 38PUR 37.205 [Xiao Nan] DEBUG com.example.test.Test2-No smoke, take a break!

Use the correct pose for wait-notify:

Synchronized (lock) {while (condition not valid) {lock.wait ()}} / / another thread synchronized (lock) {lock.notifyAll ();}

The main points for thread communication by calling the wait () and notify () series methods are as follows:

(1) before calling the wait () and notify () type methods of a synchronization object locko, you must obtain the monitor lock of the lock object, so the wait () and notify () type methods must be placed in the synchronized (locko) synchronization block. If no monitor lock is obtained, JVM will report an IllegalMonitorStateException exception.

(2) while is used to judge the condition when the wait () method is called. If you wait under certain conditions, you can't use if statement to judge the condition at once, but use while loop to judge repeatedly. Only in this way can you continue to check the conditions of the wait after the thread is awakened and wait if the conditions are not met.

This is the end of the content of "how to use the wait-notify method correctly in Java". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report