线程通信
1. wait / notify
要想执行 wait() / notify() / notifyAll() 这些方法,必须首先获得对象的监视器
换言之,这些方法必须在 synchronized 中执行
package com.example.demo22; import java.util.LinkedList; public class App2 { public static void main(String[] args) { final Factory factory = new Factory(); Thread producer = new Thread(new Runnable() { @Override public void run() { try { while (true) { factory.offer(); } } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread consumer = new Thread(new Runnable() { @Override public void run() { try { while (true) { factory.take(); } } catch (InterruptedException e) { e.printStackTrace(); } } }); producer.start(); consumer.start(); } } class Factory { private LinkedList<Object> container = new LinkedList<>(); private Integer capacity = 5; public synchronized void offer() throws InterruptedException { while (container.size() == capacity) { wait(); } int e = (int) Math.ceil(Math.random() * 100); container.push(e); System.out.println("生产" + e); notify(); } public synchronized void take() throws InterruptedException { while (container.size() == 0) { wait(); } Object e = container.poll(); System.out.println("消费" + e); notify(); } }
2. Condition
package com.example.demo22; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class App { public static void main(String[] args) { final Worker worker = new Worker(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { worker.red(); } } }).start(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { worker.green(); } } }).start(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { worker.yellow(); } } }).start(); } } class Worker { private final Lock lock = new ReentrantLock(); private final Condition conditionA = lock.newCondition(); private final Condition conditionB = lock.newCondition(); private final Condition conditionC = lock.newCondition(); private Integer signal = 1; public void red() { lock.lock(); try { while (signal != 1) { conditionA.await(); } System.out.println("Red"); signal = 2; conditionB.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void green() { lock.lock(); try { while (signal != 2) { conditionB.await(); } System.out.println("Green"); signal = 3; conditionC.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void yellow() { lock.lock(); try { while (signal != 3) { conditionC.await(); } System.out.println("Yellow"); signal = 1; conditionA.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } }
3. wait()
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
调用wait()方法会造成当前线程等待,直到另一个线程调用这个对象的notify()或者notifyAll()方法,或者其它线程打断当前线程,或者时钟周期耗尽。
调用wait()方法必须当前线程首先获得这个对象的监视器。线程释放对象的监视器的所有权,并等待直到另一个线程通知由于这个对象的监视器造成等待的线程来唤醒(通过调用notify()或notifyAll()方法)。线程等待直到它再次获得对象的监视器所有权。
synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condition }
4. notify()
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation.
唤醒一个在对象的监视器等待的线程。如果有多个线程等待在该对象的监视器上,它们中的一个会被选中唤醒。这个选中是任意的,并且取决于具体实现。
5. notifyAll()
Wakes up all threads that are waiting on this object's monitor.
唤醒在该对象的监视器上等待的所有线程