java多线程(7)---Condition
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】
java多线程(7)---Condition的更多相关文章
- Java多线程——Lock&Condition
Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. package ...
- java 多线程 day13 condition 线程通信
/** * Created by chengtao on 17/12/5. * Condition 类似 wait和notify,解决线程间的同步问题 */ import java.util.conc ...
- 玩转Java多线程(Lock.Condition的正确使用姿势)
转载请标明博客的地址 本人博客和github账号,如果对你有帮助请在本人github项目AioSocket上点个star,激励作者对社区贡献 个人博客:https://www.cnblogs.com/ ...
- Java多线程系列--“JUC锁”06之 Condition条件
概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...
- Java多线程——Condition条件
简介 Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signa ...
- Java多线程(九)之ReentrantLock与Condition
一.ReentrantLock 类 1.1 什么是reentrantlock java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...
- Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...
随机推荐
- 如何用js去判断当前是否在微信中打开的链接页面
function is_weixin() { var ua = navigator.userAgent.toLowerCase(); if (ua.match(/MicroMessenger/i) = ...
- Spring基础知识备案
关于@Value注解不能为静态变量赋值的问题 // eg:(xxx.ooo.value=100) 以下这种方式,来自配置文件的属性值无法注入: public class XxxUtils { @Val ...
- SQL增删改语句
一,插入数据 1.使用 insert ...values 语句插入单行或多行元组数据 insert into 表名 (列名,列名,...,列名) values 值 表名:指被插入数据的表名 列名: ...
- Laravel修改验证提示信息为中文
1.覆盖提示信息: 打开resource/lang/en/validation.php注释掉英文提示信息 $ sudo vim resource/lang/en/validation.php 将下面的 ...
- D3---01基础的柱状图制作(转)
---文章转自 http://d3.decembercafe.org/index.html ,Created by 十二月咖啡馆. 一个完整的柱形图包含三部分:矩形.文字.坐标轴. 首先要布置一个大 ...
- Numpy 基础运算1
# -*- encoding:utf-8 -*- # Copyright (c) 2015 Shiye Inc. # All rights reserved. # # Author: ldq < ...
- angular1.3 video
video标签动态获取播放链接是出现 Error: $interpolate:interr Interpolation Error Error: $sce:insecurl Processing of ...
- Html开发中document.getElementByTagName无法找到所有DOM元素的问题解决方法
let eleList = document.querySelectorAll('li') for (let i = 0; i < eleList.length; i++) { // 遍历操作 ...
- pip离线安装依赖包
pip安装离线本地包 导出本地已有的依赖包 pip freeze > requirements.txt 将依赖包下载到本地 # 下载到当前目录,指定pip源 pip download -r re ...
- IIS 接口访问404
IIS->网站->ASP->启用父路径(true)