之前在写显示锁的是后,在显示锁的接口中,提到了new Condition这个方法,这个方法会返回一个Condition对象

简单介绍一下

Condition接口:

  任意一个Java对象,都拥有一组监视器方法(定义在java.lang.Object上),主要包括wait()、wait(long timeout)、notify()以及notifyAll()方法,这些方法与synchronized同步关键字配合,可以实现等待/通知模式。之前写过一篇线程之间的协作(等待通知模式)是使用Object的wait和notify/notifyAll+Synchronized写的

  换而言之,synchronized关键字想要实现等待/通知模式,需要调用以上的四种方法。

  然后我们的Condition接口也提供了能够实现等待/通知模式,是与Lock配合实现的。

  我感觉这个Condition和那个差不多,也是用来完成线程之间的协作的

  但是二者在使用方式上以及功能特性上还是有所差别的。

Object对比Condition:

由此表可以看出,condition接口可以有多个等待队列,而object监视器方法只有一个队列,而且还不支持在等待状态响应中断,还不支持当前线程释放锁并进入等待状态到将来的某个时间。

示例:

  也不打算写新的示例了,用这个Condition接口改造一下之前使用等待通知模式的那个案例吧

  Condition定义了等待/通知两种类型的方法,当前线程调用这些方法时,需要提前获取到Condition对象关联的锁。Condition对象是由Lock对象(调用Lock对象的newCondition()方法)创建出来的。其实就是,Condition是依赖Lock对象的。就像使用wait/notify需要依赖Synchronized锁一样,Condition的使用方式比较简单,需要注意在调用方法前获取锁

创建等待通知类

package org.dance.day4.condition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* 类说明:使用Condition接口实现等待通知模式
*/
public class ExpressCond { public final static String CITY = "ShangHai"; /**
* 快递运输里程数
*/
private int km; /**
* 快递到达地点
*/
private String site; /**
* 创建显示锁
*/
private final Lock lock = new ReentrantLock(); /**
* 检测城市变化
*/
private final Condition siteCond = lock.newCondition(); /**
* 检测公里数变化
*/
private final Condition kmCond = lock.newCondition(); public ExpressCond() {
} public ExpressCond(int km, String site) {
this.km = km;
this.site = site;
} /* 变化公里数,然后通知处于wait状态并需要处理公里数的线程进行业务处理*/
public void changeKm() {
// 获取锁
lock.lock();
try {
this.km = 101;
// 唤醒在kmCond 上 等待的线程
kmCond.signal();
} finally {
lock.unlock();
}
} /* 变化地点,然后通知处于wait状态并需要处理地点的线程进行业务处理*/
public void changeSite() {
// 获取锁
lock.lock();
try {
this.site = "BeiJing";
// 唤醒在siteCond 上 等待的线程
siteCond.signal();
} finally {
lock.unlock();
}
} /*当快递的里程数大于100时更新数据库*/
public void waitKm() {
lock.lock();
try {
while (this.km <= 100) {
try {
kmCond.await();
} catch (InterruptedException e) {
// 处理线程中断
Thread.currentThread().interrupt();
e.printStackTrace();
}
System.out.println("check km thread[" + Thread.currentThread().getId()
+ "] is be notifed.");
}
} finally {
lock.unlock();
}
System.out.println("the Km is " + this.km + ",I will change db");
} /*当快递到达目的地时通知用户*/
public void waitSite() {
lock.lock();
try {
while (CITY.equals(this.site)) {
try {
siteCond.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("check site thread[" + Thread.currentThread().getId()
+ "] is be notifed.");
}
} finally {
lock.unlock();
}
System.out.println("the site is " + this.site + ",I will call user");
}
}

通过代码可以看见,我们一个锁,是可以携带多个等待队列的

创建测试类

package org.dance.day4.condition;

/**
*类说明:测试Lock和Condition实现等待通知
*/
public class TestCond {
private static ExpressCond express = new ExpressCond(0,ExpressCond.CITY); /*检查里程数变化的线程,不满足条件,线程一直等待*/
private static class CheckKm extends Thread{
@Override
public void run() {
express.waitKm();
}
} /*检查地点变化的线程,不满足条件,线程一直等待*/
private static class CheckSite extends Thread{
@Override
public void run() {
express.waitSite();
}
} public static void main(String[] args) throws InterruptedException {
for(int i=0;i<3;i++){
new CheckSite().start();
}
for(int i=0;i<3;i++){
new CheckKm().start();
} Thread.sleep(1000);
express.changeKm();//快递里程变化
}
}

执行结果:

check km thread[14] is be notifed.
the Km is 101,I will change db

通过执行结果,我们可以清晰的看到,他是直接唤醒了,在公里数变化上等待的线程的,在之前的等待通知模式中,也就是wait/notify/notifyAll+Sync实现的等待通知模式中,推荐大家使用notifyAll()来唤醒正在等待中的线程,但是在使用Condition接口中,推荐大家使用signal,而不是signalAll().为啥呢?因为wait/notify/notifyAll是Object的方法,在指定的对象中等待的可能是多个线程,分别在检测不同的变量,可能造成信号的拦截,所以推荐使用全部唤醒,,但是在使用Condition上却不是,因为他是多个等待队列,他清晰的知道自己应该唤醒那个线程,所以推荐使用signal,至于Condition的实现分析暂时先不写,等写完AQS再写方便,大家理解,我感觉不是所有相关的知识都要堆在一起,要是理解不了,再深入也没用

作者:彼岸舞

时间:2020\11\04

内容关于:并发编程

本文来源于网络,只做技术分享,一概不负任何责任

Lock接口之Condition接口的更多相关文章

  1. jdk1.5多线程Lock接口及Condition接口

    jdk1.5多线程的实现的方式: jdk1.5之前对锁的操作是隐式的 synchronized(对象) //获取锁 { } //释放锁 jdk1.5锁的操作是显示的:在包java.util.concu ...

  2. java中的锁之Lock接口与Condition接口

    一.Lock源码. 1.是一个接口.一共有6个方法. 2.方法详细如下: (1)当前线程尝试获取锁.结果分两种情况,一是成功获取到锁,则返回:二是获取锁失败,则一直等待.不响应中断请求. (2)当前线 ...

  3. 并发之lock的condition接口

    13.死磕Java并发-----J.U.C之Condition 12.Condition使用总结 11.Java并发编程系列之十七:Condition接口 === 13.死磕Java并发-----J. ...

  4. Java之多线程开发时多条件Condition接口的使用

    转:http://blog.csdn.net/a352193394/article/details/39454157 我们在多线程开发中,可能会出现这种情况.就是一个线程需要另外一个线程满足某某条件才 ...

  5. 6.类似Object监视器方法的Condition接口

    在<1.有关线程.并发的基本概念>中,我们利用synchronized关键字.Queue队列.以及Object监视器方法实现了生产者消费者,介绍了有关线程的一些基本概念.Object类提供 ...

  6. Java的LockSupport工具,Condition接口和ConditionObject

    在之前我们文章(关于多线程编程基础和同步器),我们就接触到了LockSupport工具和Condition接口,之前使用LockSupport工具来唤醒阻塞的线程,使用Condition接口来实现线程 ...

  7. Condition接口

    <Java并发编程艺术>读书笔记 Condition介绍 任意一个Java对象,都拥有一组监视器方法(定义在java.lang.Object中),主要包括wait().wait(long ...

  8. Java并发Condition接口

    java.util.concurrent.locks.Condition接口提供一个线程挂起执行的能力,直到给定的条件为真. Condition对象必须绑定到Lock,并使用newCondition( ...

  9. Condition接口及其主要实现类ConditionObject源码浅析

    1.引子 任意一个Java对象,都拥有一组监视器方法(定义在java.lang.Object上),主要包括wait().wait(long timeout).notify()以及notifyAll() ...

随机推荐

  1. Maven环境搭建及常用命令、生命周期

    一.下载maven包,解压 二.配置环境变量,MAVEN_PATH=解压路径 添加到path中 三.测试  mvn -v 查看maven版本 四.设置本地仓库的路径 在conf文件夹下的setting ...

  2. mybatis基础使用

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis .20 ...

  3. Centos-当前和过去登入系统用户信息-last

    last 获取当前和过去登入系统的用户相关信息,执行last指令的时候会默认读取/var/log/wtmp文件 相关参数 -a 把客户端IP显示到最后一列 -R 不显示客户端IP地址或主机名 -n 显 ...

  4. Java 文件 IO 操作

    window 路径分割符: \ 表示 windows 系统文件目录分割符 java 代码在 windows 下写某个文件的话需要下面的方式 D:\\soft\\sdclass.txt  其中一个单斜杠 ...

  5. keepass+坚果云管理我的密码

    目录 前言 下载安装KeePass 创建一个数据库 配置坚果云 手机用坚果云 总结 前言     KeePass是一款免费.小巧.绿色且开源的密码管理工具,多年来一直深受大众的好评,它能为用户提供一个 ...

  6. Matlab中fspecial的用法

    来源:https://blog.csdn.net/hustrains/article/details/9153553 Fspecial函数用于创建预定义的滤波算子,会与imfilter搭配使用,其语法 ...

  7. 【题解】SP10570 【LONGCS - Longest Common Substring】

    \(\color{Red}{Link}\) \(\text{Solution:}\) 还是\(\text{Suffix Tree.}\) 根据\(\color{Blue}{Link}\)我们可以得到一 ...

  8. ansible-playbook流程控制-when条件判断

    1. ansible-playbook添加判断     when相当于shell脚本里的if 判断,when语句就是用来实现这个功能的,它是一个jinja2的语法,但是不需要双大括号,用法很简单  1 ...

  9. 【最大匹配+二分答案】HDU 2236 无题II

    题目内容 这是一个简单的游戏,在一个\(n×n\)的矩阵中,找\(n\)个数使得这\(n\)个数都在不同的行和列里并且要求这\(n\)个数中的最大值和最小值的差值最小. 输入格式 输入一个整数\(T\ ...

  10. rabbitmq 延时队列 插件方式实现 每条消息都延时自己时间

    上篇文章的延时是加到队列上的 通过死信过时推送 ,缺点就是不能每条消息定义自己的过时时间而且每次有新的过时时间,要新建一个交换机和队列 https://www.cnblogs.com/brady-wa ...