Brief introduction of methods
wait() method: When a task encounters a call to wait() in the method, the execution of the thread is suspended and the lock is released. So another task can get the lock. That's why you should call this method in a synchronized block of code or synchronized method
notify()/notifyAll() method: Make the waiting thread regain the lock, resume execution from wait(), notify() will randomly restore a waiting thread, and notifyAll() method will restore all waiting threads.
Note: Just because a thread is awakened does not mean that it immediately acquires the lock of the object. Only after calling notify() or notifyAll() and exiting the synchronized block, releasing the lock of the object, and having to finish the task of the current thread, can the other threads acquire the lock execution.-
A simple example
public class Test { public static Object object = new Object(); public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); thread1.start(); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } thread2.start(); } static class Thread1 extends Thread{ @Override public void run() { synchronized (object) { try { object.wait(); } catch (InterruptedException e) {} System.out.println("thread"+Thread.currentThread().getName()+"Locks were acquired"); } } } static class Thread2 extends Thread{ @Override public void run() { synchronized (object) { object.notify(); System.out.println("thread"+Thread.currentThread().getName()+"Called object.notify()"); } System.out.println("thread"+Thread.currentThread().getName()+"Release the lock."); } } } thread1 After the task is executed, it will be suspended, and then thread2 Execute tasks, wake up thread 1, but thread2 After the synchronization block and tasks have to be executed, thread1 Can from wait()Mid recovery
-
Using wait()/notify() method to simulate producers and consumers
Producer:import java.util.ArrayList; /** * @author hetiantian * Simulated producers produce food */ public class Producer implements Runnable { //It can only produce five at a time, and if it reaches five, it will have to wait for consumers to eat it before they can continue to produce. private static ArrayList<Food> foods = new ArrayList<>(5); static int id; //Object mark public Producer(ArrayList<Food> foods) { this.foods = foods; } //Simulated production process public static void productFood() throws InterruptedException { while (true) { Food f = new Food(id++); synchronized (foods) { if (foods.size() >= 5) { foods.wait(); //If it is greater than or equal to 6, it will be suspended and the next operation will continue only after it has been consumed. } else { foods.add(f); System.out.println("Production:" + f); } } } } @Override public void run() { try { productFood(); } catch (InterruptedException e) { e.printStackTrace(); } } } //Consumer: import java.util.ArrayList; /** * @author hetiantian * Analog consumer threads */ public class Consumer implements Runnable { private static ArrayList<Food> foods = new ArrayList<>(5); public Consumer(ArrayList<Food> foods) { this.foods = foods; } public static void eatFood() throws InterruptedException { while (true) { int last = foods.size() - 1; Food f; synchronized (foods) { if (last < 0) { foods.notify(); //If it's eaten up, release the lock and let the producer continue to execute it. } else { f = foods.get(last); System.out.println("Consumption:" + f); foods.remove(last); } } } } @Override public void run() { try { eatFood(); } catch (InterruptedException e) { e.printStackTrace(); } } } //Test class: import java.util.ArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * @author hetiantian * Consumer Producer Testing Class */ public class ProductAndConsumerTest { private static ArrayList<Food> foods = new ArrayList<>(5); public static void main(String[] args) throws InterruptedException { Producer p = new Producer(foods); Consumer c = new Consumer(foods); ExecutorService es = Executors.newCachedThreadPool(); es.execute(p); es.execute(c); TimeUnit.SECONDS.sleep(7); //Close task es.shutdownNow(); } }
Condition briefly introduces:
Condition's await() and signal() are more secure and efficient ways to achieve inter-thread collaboration. await() in Conditon corresponds to wait() in Object, signal() in Condition corresponds to notify() in Object, signalAll() in Condition corresponds to notifyAll() in Object. Therefore, Condition is more recommended.
Condition relies on the Lock interface, and the basic code for generating a Condition is lock.newCondition().
Calling Condition's await() and signal() methods must be protected by lock, that is, between lock.lock() and lock.unlock.
wait(),notify(),notifyAll() method and Condition interface in java concurrency
Posted by meshi on Fri, 15 Feb 2019 00:15:19 -0800