大纲:
- wait、notify、notifyAll
- Condition
- 生产消费者
一、wait、notify、notifyAll
- wait、notify、notifyAll是Object的本地final方法。
- 在一个线程中调用object.wait()可以使当先线程阻塞并交出锁(object)。
- 既然obj.wait操作会交出锁,那必然在synchronized(obj)代码块内,且2个obj为统一对象。
- 使用obj.notify()能够唤醒任意一个等待obj锁的线程,obj.notifyAll()能够唤醒所有等待obj锁的线程。同样notify操作也必须在synchronized(obj)代码块内。
- 线程等待是锁对象的方法而不是线程的方法,试想在多个synchronized嵌套代码块内,调用wait()是不是应该指定释放哪一个锁对象。
二、Condition
- Condition接口依赖于Lock接口,可以通过lock.newCondition() 。
- wait,notify操作都是控制一个锁下面的线程。Condition可以将一个锁下面的线程分成多种情况分别控制。
- 调用Condition的await()和signal()方法也需要在lock()-unlock()代码块内。
- Condition接口的await对应Object的wait方法 ,signal对应notify方法 ,signalAll对应notifyAll方法 。
- 使用Condition也更加高效。
- void awaitUninterruptibly():不响应中断的await方法。
- long awaitNanos(long nanosTimeout) throws InterruptedException:await上增加超时响应,返回值=nanosTimeout-消耗时间。
三、生产消费者
生产者、消费者线程轮流执行,操作同一个资源。
消费者:
public class Comsumer implements Runnable { Resource resource; public Comsumer(Resource resource){ this.resource = resource; } @Override public void run() { try { resource.comsume(); } catch (InterruptedException e) { e.printStackTrace(); } } }
生产者:
public class Producer implements Runnable { Resource resource; public Producer(Resource resource){ this.resource = resource; } @Override public void run() { try { resource.produce(); } catch (InterruptedException e) { e.printStackTrace(); } } }
资源对象-wait,notify实现:
public class Resource { private int r = 0; private Object lock = new Object(); private boolean produced = false; public void produce() throws InterruptedException { synchronized(lock){ while (true){ while (produced){ lock.wait(); } r++; System.out.println(Thread.currentThread().getName()+"线程成产1个,当前剩余:"+r); produced = true; lock.notifyAll(); } } } public void comsume() throws InterruptedException { synchronized(lock){ while (true){ while (!produced){ lock.wait(); } r--; System.out.println(Thread.currentThread().getName()+"线程消费1个,当前剩余:>>"+r); produced = false; lock.notifyAll(); } } } }
资源对象-condition实现:
public class Resource { private int r = 0; private boolean produced = false; Lock lock = new ReentrantLock(); Condition proCondition = lock.newCondition(); Condition comCondition = lock.newCondition(); public void produce() throws InterruptedException { lock.lock(); try { while (true){ while (produced){ proCondition.await(); } r++; System.out.println(Thread.currentThread().getName()+"线程成产1个,当前剩余:"+r); produced = true; comCondition.signal(); } }finally { lock.unlock(); } } public void comsume() throws InterruptedException { lock.lock(); try { while (true){ while (!produced){ comCondition.await(); } r--; System.out.println(Thread.currentThread().getName()+"线程消费1个,当前剩余:>>"+r); produced = false; proCondition.signal(); } }finally { lock.unlock(); } } }
测试类
class TestWait { public static void main(String[] args) { Resource r = new Resource(); Producer producer = new Producer(r); Comsumer comsumer = new Comsumer(r); new Thread(producer).start(); new Thread(producer).start(); new Thread(producer).start(); new Thread(comsumer).start(); new Thread(comsumer).start(); new Thread(comsumer).start(); } }