多线程-Condition
关键字synchronized与wait和notify/notifyAll方法相结合可以实现等待/通知模式,类ReentrantLock也可以实现同样的功能,但需要借助于Condition对象。Condition类是JDK5中出现的技术,使用它有更好的灵活性,比如可以实现多路通知功能,也就是在一个Lock对象里面可以创建多个Condition(即对象监视器)实例,线程对象可以注册在指定的Condition中,从而可以有选择性地进行线程通知,在调度线程上更加灵活。
在使用notify/notifyAll方法进行通知时,被通知的线程却是由JVM随机选择的。但使用ReentrantLock结合Condition类是可以实现前面介绍过的“选择性通知”,这个功能是非常重要的,而且在Condition类中是默认提供的。
而synchronized就相当于整个Lock对象中只有一个单一的Condition对象,所有的线程都注册到它一个对象的身上。线程开始notifyAll时,需要通知所有的WAITING线程,没有选择权,会出现相当大的效率问题。
package org.github.lujiango; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class Test06 { static class Service {
private Lock lock = new ReentrantLock();
public Condition condition = lock.newCondition(); public void await() {
try {
lock.lock();
System.out.println("await time: " + System.currentTimeMillis());
condition.await();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void signal() {
try {
lock.lock();
System.out.println("signal time: " + System.currentTimeMillis());
condition.signal();
} finally {
lock.unlock();
}
}
} static class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
this.service = service;
} @Override
public void run() {
service.await();
}
} public static void main(String[] args) throws InterruptedException {
Service service = new Service();
ThreadA a = new ThreadA(service);
a.start();
Thread.sleep(3000);
service.signal();
}
}
如果想单独唤醒部分线程该怎么处理呢?这时就有必要使用多个Condition对象了,也就是Condition对象可以唤醒部分指定线程,有助于提升程序运行的效率。可以先对线程进行分组,然后在唤醒指定组中的线程。
package org.github.lujiango; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class Test07 { static class MyService {
private Lock lock = new ReentrantLock();
public Condition condition1 = lock.newCondition();
public Condition condition2 = lock.newCondition(); public void await1() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " begin await1");
condition1.await();
System.out.println(Thread.currentThread().getName() + " end await1");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void await2() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " begin await2");
condition2.await();
System.out.println(Thread.currentThread().getName() + " end await2");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void signalAll1() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " signalAll1");
condition1.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void signalAll2() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " signalAll2");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} } static class ThreadA extends Thread {
private MyService service; public ThreadA(MyService service) {
this.service = service;
} @Override
public void run() {
service.await1();
}
} static class ThreadB extends Thread {
private MyService service; public ThreadB(MyService service) {
this.service = service;
} @Override
public void run() {
service.await2();
}
} public static void main(String[] args) throws InterruptedException {
MyService service = new MyService();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
Thread.sleep(3000);
service.signalAll2();
} }
实现生产者/消费者模式:一对一交替打印
package org.github.lujiango; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class Test08 { static class Service {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private Boolean hasValue = Boolean.FALSE; public void producer() {
try {
lock.lock();
while (hasValue) {
condition.await();
}
System.out.println("producer");
hasValue = Boolean.TRUE;
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void consumer() {
try {
lock.lock();
while (!hasValue) {
condition.await();
}
System.out.println("consumer");
hasValue = Boolean.FALSE;
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} } static class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
this.service = service;
} @Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
service.producer();
}
}
} static class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
this.service = service;
} @Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
service.consumer();
}
}
} public static void main(String[] args) {
Service service = new Service();
ThreadA a = new ThreadA(service);
a.start();
ThreadB b = new ThreadB(service);
b.start();
} }
多线程-Condition的更多相关文章
- java多线程-Condition
Condition 将 Object 监视器方法(wait.notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set ...
- Java多线程——Condition条件
简介 Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signa ...
- Java多线程Condition定点通知
多线程之间按顺序调用,实现A->B->C三个线程启动,要求如下:A打印5次,B打印10次,C打印15次接着 A打印5次,B打印10次,C打印15次 来10轮 package com.yan ...
- Python 多线程 Condition 的使用
Condition Condition(条件变量)通常与一个锁关联.需要在多个Contidion中共享一个锁时,可以传递一个Lock/RLock实例给构造方法,否则它将自己生成一个RLock实例. 可 ...
- python多线程--Condition(条件对象)
Condition class threading.Condition(lock=None 这个类实现条件变量对象.条件变量允许一个或多个线程等待,知道它们被另一个线程唤醒. 如果给出了lock参数而 ...
- java多线程 -- Condition 控制线程通信
Api文档如此定义: Condition 将 Object 监视器方法(wait.notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对 ...
- [Python 多线程] Condition (十)
Condition常用于生产者.消费者模型,为了解决生产者消费者速度匹配问题. 构造方法Condition(lock=None),可以传入一个Lock或RLock对象,默认RLock. 方法: acq ...
- 关于Python多线程condition变量的应用
''' 所谓条件变量,即这种机制是在满足了特定的条件后,线程才可以访问相关的数据. 它使用Condition类来完成,由于它也可以像锁机制那样用,所以它也有acquire方法和release方法,而且 ...
- Java之多线程开发时多条件Condition接口的使用
转:http://blog.csdn.net/a352193394/article/details/39454157 我们在多线程开发中,可能会出现这种情况.就是一个线程需要另外一个线程满足某某条件才 ...
随机推荐
- [Asp.net本质论]重新认识url
引言 之前大部分时间,一直在学c#,打算将asp.net本质论好好学习一下,之前虽然已经看了两边了,总感觉看过,没做笔记等于白看了,一点印象也没.打算将书中的代码,自己实现一下,在敲代码时要一直反思, ...
- ubuntu-14.04.5 升级sshd到指定版本openssh-7.7p1,openssl-1.1.0h。
升级步骤 wget https://wps-oss.oss-cn-shenzhen.aliyuncs.com/openssh_update.tar.gz tar xvf openssh_update. ...
- 查看SQLServer的QUOTED_IDENTIFIER等配置
DBCC USEROPTIONS SELECT SESSIONPROPERTY('QUOTED_IDENTIFIER') quotedidentifier SELECT SESSIONPROPERTY ...
- CMakeFile命令之file
file:文件操作命令. file(WRITE filename "message towrite"... ) WRITE 将一则信息写入文件’filename’中,如果该文件存在 ...
- dcmtk dcmmkdir 使用帮助
例子: dcmmkdir --recurse --input-directory C:\TEMP DICOM --output-file C:\TEMP\DCMDIR --recurse 递归 -- ...
- vue项目构建实战基础知识:SPA理解/RESTful接口介绍/static目录配置/axios封装/打包时map文件去除
一.SPA 不是指水疗.是 single page web application 的缩写.中文翻译为 单页应用程序 或 单页Web应用,更多解释请自行搜索. 所有的前端人员都应该明白我们的页面的 u ...
- 基于QTP的自己主动化測试框架介绍
继前面用了七章介绍了基于QTP的自己主动化測试框架,以下再用几个视频再补充一下. 视频一:基本框架特点介绍说明 .框架的特点从正反两面进行了分析以及主要思想 http://v. ...
- Java小案例-(逃离迷宫)
Java小案例-(逃离迷宫) 一,迷宫需求描述: 1,用户输入迷宫图(限制方形):字母1位墙,0为通,e为出口,m为入口,*为已访问的位置,用外围1围住迷宫 2,运行轨迹右,左,下,上 3,判断该迷宫 ...
- 阿里巴巴Android开发手册(规约)
阿里巴巴Android开发手册(规约) 学习了:https://www.cnblogs.com/jb2011/p/8487889.html 这个猛 https://blog.csdn.net/ali ...
- 批处理文件——多个QQ一键登录
偶然看到有的同学登录PC的QQ,发现他有很多QQ,每登录一个要切换一个,虽然记住了密码,但还是不方便,于是想通过批处理来实现“一键登录”的功能.以下内容为本文假想,如有雷同,实属巧合! 具体的实现步骤 ...