Condition

一、Condition概述

在线程的同步时可以使一个线程阻塞而等待一个信号,同时放弃锁使其他线程可以能竞争到锁。

在synchronized中我们可以使用Object的wait()和notify方法实现这种等待和唤醒。

在Lock可以实现相同的功能就是通过Condition。Condition中的await()和signal()/signalAll()就相当于Object的wait()和notify()/notifyAll()。

除此之外,Condition还是对多线程条件进行更精确的控制。notify()是唤醒一个线程,但它无法确认是唤醒哪一个线程。 但是,通过Condition,就能明确的指定唤醒读线程。

二、Condition和Object案例对比

案例说明:生成者在仓库满时,进入等待状态,同时唤醒消费者线程,消费者在仓库为空时,进入等待。同时唤醒生产者线程。

1、采用await()和signal()方式

(1)测试类

public class ConditionLockTest {

    public static void main(String[] args){

        //相当于仓库
Depot depot=new Depot(); //创建两个生产者一个消费者
Producer producer1=new Producer(depot);
Producer producer2=new Producer(depot);
Consumer consumer1=new Consumer(depot); //采用线程池方式
Executor executors=Executors.newFixedThreadPool(5);
executors.execute(producer1);
executors.execute(producer2);
executors.execute(consumer1);
}
} //生产者
class Producer implements Runnable { Depot depot;
public Producer(Depot depot){
this.depot=depot;
}
public void run(){
while(true){
depot.prod();
}
}
} //消费者
class Consumer implements Runnable{ Depot depot;
public Consumer(Depot depot){
this.depot=depot;
}
public void run(){
while(true){
depot.consum();
}
}
}

(2)仓库类

public class Depot {
//初始仓库为0,最大为10,超过10生产者停止生产
private int size;
private int maxSize=10; private Condition prodCondition;
private Condition consumCondition; private Lock lock;
public Depot(){ this.size=0;
this.lock=new ReentrantLock();
//可以看出Condition对象依赖于Lock锁
this.prodCondition=this.lock.newCondition();
this.consumCondition=this.lock.newCondition();
} /*
* 生产者生产方法
*/
public void prod(){ lock.lock();
try{
//如果生产超过max值,则生产者进入等待
while(size+1>maxSize){
try {
System.out.println(Thread.currentThread().getName()+"生产者进入等待状态");
prodCondition.await();
} catch (Exception e) {
e.printStackTrace();
}
}
size+=1;
System.out.println(Thread.currentThread().getName()+" 生产了一个 "+1+" 总共还有 "+size); //唤醒消费者线程
consumCondition.signal(); }finally {
lock.unlock();
}
} /*
* 消费者消费方法
*/
public void consum(){ lock.lock();
try{
//如果当前大小减去要消费的值,如果小于0的话,则进入等待
while(size-1<0){
try {
System.out.println(Thread.currentThread().getName()+" 消费者进入等待状态");
consumCondition.await(); } catch (Exception e) {
e.printStackTrace();
}
} size-=1;
System.out.println(Thread.currentThread().getName()+" 消费者消费了 "+1+" 个,总共还有 "+size);
//唤醒生产者线程
prodCondition.signal();
}finally {
lock.unlock();
}
}
}

运行结果(截取部分图)

根据结果分析可以得出:
      生产者生产产品,当超过10个,生产者会处于等待状态,直到消费者消费者消费了一个产品,生产者才会重新唤醒。

2、采用wait()和notifyAll()方法

 (1)仓库类代码(测试类代码不变)

public class Depot {
//初始仓库为0,最大为10,超过10生产者停止生产
private int size;
private int maxSize=10; public Depot(){
this.size=0;
} /*
* 生产者生产方法
*/
public synchronized void prod(){ try{
//如果生产超过max值,则生产者进入等待
while(size+1>maxSize){
try {
//采用wait方法
wait();
System.out.println(Thread.currentThread().getName()+"生产者进入等待状态");
} catch (Exception e) {
e.printStackTrace();
}
} size+=1;
System.out.println(Thread.currentThread().getName()+" 生产了一个 "+1+" 总共还有 "+size); //唤醒所有线程
notifyAll(); }finally {
}
} /*
* 消费者消费方法
*/
public synchronized void consum(){ try{
//如果当前大小减去要消费的值,如果小于0的话,则进入等待
while(size-1<0){
try {
wait();
System.out.println(Thread.currentThread().getName()+" 消费者进入等待状态"); } catch (Exception e) {
e.printStackTrace();
}
} size-=1;
System.out.println(Thread.currentThread().getName()+" 消费者消费了 "+1+" 个,总共还有 "+size);
//唤醒所有线程
notifyAll(); }finally {
}
}
}

运行结果:

对比:

首先可以看出两个都可以实现生产者消费者的工作,不过可以发现Condition的signal相对于Object的notify最大有点就是它可以唤醒指定的线程,

比如这里可以指定唤醒生产线程或者消费线程,而用notify是不能唤醒指定线程的,你只能通过notifyAll来唤醒所有。

想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。少校【14】

最新文章

  1. python笔记1-转义字符
  2. 使用用户自定义类型 CLR UDT
  3. Jenkins 命令
  4. android应用中增加权限判断
  5. eclipse优化与标准化记录
  6. NBOJv2 1004 蛤玮打扫教室(线段树区间更新区间最值查询)
  7. jquery-qrcode在线生成二维码
  8. day55
  9. solr中重跑索引
  10. Python自动化--语言基础6--模块操作之re、MySQL、Excel
  11. 利用 mount 指令解决 Read-only file system的问题
  12. Oracle Inventory Management Application Program Interface ( APIs)
  13. Flask 三方组件 WTForms
  14. [,,].length等于几
  15. MongoDB之 复制集搭建
  16. centos6.9环境下JDK安装部署
  17. CMFCPropertyGridProperty的使用
  18. 在Linode VPS上搭建离线下载神器Aria2+WEBUI管理及对国内云盘看法
  19. 基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(中)
  20. Cloud Foundry技术资料汇总

热门文章

  1. gzip解压文件报错
  2. Shell脚本学习 - 基本内容以及数据格式
  3. Unity Bolt插件 基本使用
  4. toString
  5. mvc 路由配置
  6. oracle之序列用法
  7. Elasticsearch 滚动重启 必读
  8. spring-cloud-gateway负载普通web项目
  9. vue项目中的相关插件
  10. Index API