Java multi-threaded wait() and notify() series method usage tutorial (connotation story)

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 Objectobject, 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. timeoutAn 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:

  1. When calling wait()the notify()method, the current thread must successfully obtain the lock (must be written in the synchronized code block lock), otherwise an exception will be thrown.
  2. It only takes effect on the current single shared variable, and multiple shared variables need to call the wait()method multiple times.
  3. 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 thrown InterruptExcptionand 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:

  1. Create two threads Thread0and Thread1.
  2. Let Thread0execute wait()method.
  3. At this point Thread1, the lock is obtained, and then Thread1the execution notify()method releases the lock.
  4. At this point , if Thread0the lock is obtained, Thread0it will automatically wait()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:

  1. Thread0After the method is called wait(), the object lock will be released and the execution of subsequent code will be suspended, that is, the execution of the code from wait()after the run()method to the end of the method will be suspended immediately, which is wait()the role of the method in the thread.
  2. The CPU will assign the object lock to the Thread1thread that has been waiting. After Thread1executing the notify()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.
  3. Because there are only two threads in this example, the system will give Thread1control of the lock to (if there are other threads, who gets the lock is random, Synchronizedafter all the code in the code block has been executed) Thread0It depends entirely on the mood of the CPU), Thread0will follow wait()the code after that, continue to execute until the Synchronizedend 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.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324133190&siteId=291194637