Introduction
This article explains the role of these two methods in Java wait()
, notify()
and through a standard use example, to discuss the role of these two methods and the points to pay attention to when using them. These two methods are extracted into the top-level parent class Object
object, and their status is equivalent to the toString()
method, so this article will take you Understand their usage from scratch. At the end of the article, I prepared a story about "picking up soap". Even if you haven't written code, you can understand the role of series methods in the program even if you have read this wait()
story notify()
. The 1024 Programmer's Day is an Easter egg for everyone.
1. The meaning of wait() and notify() series methods
wait()
The method is to let the current thread wait, that is, to let the thread release the lock on the shared object.
wait(long timeout)
The method can specify a timeout, after which notify()
the function will return if it is not woken up. timeout
An exception will be thrown if a negative number is passed IllegalArgumentException
.
notify()
The method will let wait()
a thread that called the series of methods release the lock and notify other threads that are waiting (calling the wait() method) to get the lock.
notifyAll()
The method wakes up all threads that were suspended by calling wait-series methods on shared variables.
Notice:
- When calling
wait()
thenotify()
method, the current thread must successfully obtain the lock (must be written in the synchronized code block lock), otherwise an exception will be thrown. - It only takes effect on the current single shared variable, and multiple shared variables need to call the
wait()
method multiple times. - If thread A
wait()
is in a blocked state after calling the method, other threads interrupt (when other threads call the A.interrupt() method) thread A, an exception will be thrownInterruptExcption
and an exception will be returned and terminated.
This is all the theoretical content. The following will show you the above content with an example, and take you step by step to analyze and implement these two methods. These two methods in multi-threading will make the program jump execution, so be sure to understand the execution of the code. process.
2. Standard code example
1. Code implementation content process description:
- Create two threads
Thread0
andThread1
. - Let
Thread0
executewait()
method. - At this point
Thread1
, the lock is obtained, and thenThread1
the executionnotify()
method releases the lock. - At this point , if
Thread0
the lock is obtained,Thread0
it will automaticallywait()
continue execution from the code after the method.
Through the above process, we can clearly see how each one works wait()
and notify()
how the two work together.
2. Code implementation:
public class ThreadWaitAndNotify {
// 创建一个将被两个线程同时访问的共享对象
public static Object object = new Object();
// Thread0线程,执行wait()方法
static class Thread0 extends Thread {
@Override
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + "初次获得对象锁,执行中,调用共享对象的wait()方法...");
try {
// 共享对象wait方法,会让线程释放锁。
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "再次获得对象锁,执行结束");
}
}
}
// Thread1线程,执行notify()方法
static class Thread1 extends Thread {
@Override
public void run() {
synchronized (object) {
// 线程共享对象,通过notify()方法,释放锁并通知其他线程可以得到锁
object.notify();
System.out.println(Thread.currentThread().getName() + "获得对象锁,执行中,调用了共享对象的notify()方法");
}
}
}
// 主线程
public static void main(String[] args) {
Thread0 thread0 = new Thread0();
Thread1 thread1 = new Thread1();
thread0.start();
try {
// 保证线程Thread0中的wait()方法优先执行,再执线程Thread1的notify()方法
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.start();
}
3. Running results
Thread-0初次获得对象锁,执行中,调用共享对象的wait()方法...
Thread-1获得对象锁,执行中,调用了共享对象的notify()方法
Thread-0再次获得对象锁,执行结束
4. Detailed explanation of the operation process:
From the results of execution, it is necessary to understand the execution order of the threads:
Thread0
After the method is calledwait()
, the object lock will be released and the execution of subsequent code will be suspended, that is, the execution of the code fromwait()
after therun()
method to the end of the method will be suspended immediately, which iswait()
the role of the method in the thread.- The CPU will assign the object lock to the
Thread1
thread that has been waiting. AfterThread1
executing thenotify()
method, it will notify other waiting threads (Thread0
) to obtain the lock, but will continue to execute the code in its own lock before handing over control of the lock. - Because there are only two threads in this example, the system will give
Thread1
control of the lock to (if there are other threads, who gets the lock is random,Synchronized
after all the code in the code block has been executed)Thread0
It depends entirely on the mood of the CPU),Thread0
will followwait()
the code after that, continue to execute until theSynchronized
end of the code block, and return the control of the object lock to the CPU.
3. Use life stories to tell the thread's waiting to wake up
The waiting and wake-up mechanism of Java threads is implemented by wait()
methods and notify()
methods. For better understanding, let me give an easy-to-understand and down-to-earth example. People who do not understand the code can also understand the role of these two methods.
Example: The story of picking up soap
Suppose two programmers take a bath and only bring a bar of soap. How can two people use a bar of soap to bathe? 3 scenarios will occur:
1. Lao Wang and Lao Li (expert programmers):
Lao Wang and Lao Li get the soap at random. For example, Lao Wang gets the soap first, then uses the soap, then lets the soap out and uses it later. Lao Li got the soap, and after using it for a while, he informed Lao Wang, "I don't need it anymore." After Lao Wang heard the words, he picked up the soap and continued to use it from the place where he used it last time. When the two take a bath, you come and I share a piece of soap, which is very harmonious.
Programming language description:
Lao Wang got the lock at random, and after using it for a while, he called the wait() method, handed over the lock, and waited by himself. Lao Li gets the lock. After using it, he notifies Lao Wang through notify(), and after Lao Li runs out, Lao Wang gets the lock again and continues to execute... This method is thread-safe and can be allocated reasonably resource usage, that's the benefit of waiting to wake up.
2. Brother Wang and Brother Li (ordinary programmers):
Brother Wang and Brother Li got the soap at random. For example, Brother Wang got it first, and then Brother Wang kept occupying it. He didn't give the soap to Brother Li until he finished washing. During this period, Brother Li could only dry and rub in the shower, and he had no chance to touch the soap at all. I think Brother Li must think that Brother Wang is very selfish and doesn't know how to be polite. Brother Li's experience is not very good.
Programming language description: Brother Wang and Brother Li are two threads. After Brother Wang gets the lock, he will use it until the content in the synchronization code block is completely executed. Then hand over the lock to Brother Li for use. In this way, every time one thread is executed, the other will be executed, which is thread-safe.
3. Xiao Wang and Xiao Li (novice programmers):
Xiao Wang and Xiao Li competed for soap as soon as they took a bath. When the soap was in Xiao Wang's hand, Xiao Wang was still using it, and Xiao Li rushed over, so there was a scene where the two rubbed a piece of soap together! This picture is neither elegant nor safe.
Programming language description:
If two threads access the same resource without locking and controlling it, there will be a chaotic scene, which is thread insecurity. Two threads may operate on the same shared variable at the same time, causing the shared variable to get out of control and the final result to be chaotic.
We can see that the cooperation between Lao Wang and Lao Li is the most tacit understanding, and the utilization rate of soap is the highest. Although Brother Zhang and Brother Li can also allocate resources, their utilization of resources is not efficient. There is always one person who has to wait for the other person to use it completely before they can get it. Xiao Zhang and Xiao Li didn't know how to cooperate at all. They both wanted to compete for soap, but in the end, no one used it well. The scene fell into chaos, and the picture couldn't bear to look directly. . .
( This article was published on the 1024 Programmer's Day in 2020. This story pays tribute to all programmers. 1024+996=2020 )
Summarize
Through the three examples in the above story, I think you should understand the usage scenarios and benefits of the thread's waiting to wake up. After you understand these popular examples, you can play its ideas in the program, so as to use wait()
and notify()
method, Build a reasonable program flow and elegantly implement the shared use of variables between threads. If you like this article, please like it, and wish everyone a happy 1024 holiday.