Lock中使用Condition实现等待通知
- Condition类有很好的灵活性,可以实现多路通知功能,一个Lock对象中可以创建多个Condition对象实例,线程对象可以注册在指定的Condition中,进而有选择的进行线程通知,在调度线程上更加灵活
- wait与notify/notifyAll进行等待通知时,被通知的线程是随机的,但是Condition与Lock结合的通知是有选择性的通知
- synchronized就相当于整个Lock对象中只有一个单一的Condition对象,所有线程对象都注册在一个Condition对象身上,线程开始notifyAll时,需要通知所有的WAITING线程,没有选择性,会出现很大的效率问题
public class MyService {
private Lock lock = new ReentrantLock();
public Condition condition = lock.newCondition();
public void await(){
try {
lock.lock();
System.out.println("await时间为"+System.currentTimeMillis());
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signal(){
try {
lock.lock();
System.out.println("signal时间为"+System.currentTimeMillis());
condition.signal();
} finally {
lock.unlock();
}
}
}
public class MyThread extends Thread {
private MyService service;
public MyThread(MyService service) {
this.service = service;
}
@Override
public void run() {
service.await();
}
}
public class Run {
public static void main(String[] args) {
try {
MyService service = new MyService();
MyThread mt = new MyThread(service);
mt.start();
Thread.sleep(3000);
service.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
-------------------------------------------------------打印输出-------------------------------------------------------
await时间为1537949157830
signal时间为1537949160830
Condition类中的await方法相当于Object类中的wait方法
Condition类中的signal/signalAll方法相当于Object类中的notify/notifyAll方法
案例2
public class MyService {
private Lock lock = new ReentrantLock();
public Condition condition = lock.newCondition();
public void awaitA(){
try {
lock.lock();
System.out.println("begin awaitA时间为"+System.currentTimeMillis()+ " ThreadName="+Thread.currentThread().getName());
condition.await();
System.out.println("end awaitA时间为"+System.currentTimeMillis()+ " ThreadName="+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void awaitB(){
try {
lock.lock();
System.out.println("begin awaitB时间为"+System.currentTimeMillis()+ " ThreadName="+Thread.currentThread().getName());
condition.await();
System.out.println("end awaitB时间为"+System.currentTimeMillis()+ " ThreadName="+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signalAll(){
try {
lock.lock();
System.out.println("signalAll时间为"+System.currentTimeMillis()+ " ThreadName="+Thread.currentThread().getName());
condition.signalAll();
} finally {
lock.unlock();
}
}
}
线程
public class ThreadA extends Thread {
private MyService service;
public ThreadA(MyService service) {
this.service = service;
}
@Override
public void run() {
service.awaitA();
}
}
-------------------------------------------------
public class ThreadB extends Thread {
private MyService service;
public ThreadB(MyService service) {
this.service = service;
}
@Override
public void run() {
service.awaitB();
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
MyService service = new MyService();
ThreadA a = new ThreadA(service);
a.setName("A");
ThreadB b = new ThreadB(service);
b.setName("B");
a.start();
b.start();
Thread.sleep(3000);
service.signalAll();
}
}
-------------------------------------------------------打印输出-------------------------------------------------------
begin awaitA时间为1537951494924 ThreadName=A
begin awaitB时间为1537951494925 ThreadName=B
signalAll时间为1537951497924 ThreadName=main
end awaitA时间为1537951497924 ThreadName=A
end awaitB时间为1537951497925 ThreadName=B
线程A和B都被唤醒了
使用多个Condition实现通知部分线程
想要单独唤醒部分线程,就需要使用多个Condition对象,先对线程进行分组,Condition对象可以唤醒部分指定线程,有助于提高程序运行效率
public class MyService {
private Lock lock = new ReentrantLock();
public Condition conditionA = lock.newCondition();
public Condition conditionB = lock.newCondition();
public void awaitA(){
try {
lock.lock();
System.out.println("begin awaitA时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
conditionA.await();
System.out.println("--end awaitA时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void awaitB(){
try {
lock.lock();
System.out.println("begin awaitB时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
conditionB.await();
System.out.println("--end awaitB时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signAll_A(){
try {
lock.lock();
System.out.println("signAll_A时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
conditionA.signalAll();
} finally {
lock.unlock();
}
}
public void signAll_B(){
try {
lock.lock();
System.out.println("signAll_B时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
conditionB.signalAll();
} finally {
lock.unlock();
}
}
}
线程
public class ThreadA extends Thread {
private MyService service;
public ThreadA(MyService service) {
this.service = service;
}
@Override
public void run() {
service.awaitA();
}
}
-----------------------------------------------
public class ThreadB extends Thread {
private MyService service;
public ThreadB(MyService service) {
this.service = service;
}
@Override
public void run() {
service.awaitB();
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
MyService service = new MyService();
ThreadA a = new ThreadA(service);
a.setName("A");
ThreadB b = new ThreadB(service);
b.setName("B");
a.start();
b.start();
Thread.sleep(3000);
service.signAll_A();
}
}
-------------------------------------------------------打印输出-------------------------------------------------------
begin awaitA时间为1537952328573 ThreadName=A
begin awaitB时间为1537952328573 ThreadName=B
signAll_A时间为1537952331572 ThreadName=main
--end awaitA时间为1537952331572 ThreadName=A
线程A被唤醒了,但是线程B仍然在等待
Lock中使用Condition实现等待通知的更多相关文章
- 再谈AbstractQueuedSynchronizer:共享模式与基于Condition的等待/通知机制实现
共享模式acquire实现流程 上文我们讲解了AbstractQueuedSynchronizer独占模式的acquire实现流程,本文趁热打铁继续看一下AbstractQueuedSynchroni ...
- 再谈AbstractQueuedSynchronizer2:共享模式与基于Condition的等待/通知机制实现
共享模式acquire实现流程 上文我们讲解了AbstractQueuedSynchronizer独占模式的acquire实现流程,本文趁热打铁继续看一下AbstractQueuedSynchroni ...
- Java 并发编程-再谈 AbstractQueuedSynchronizer 2:共享模式与基于 Condition 的等待 / 通知机制实现
共享模式acquire实现流程 上文我们讲解了AbstractQueuedSynchronizer独占模式的acquire实现流程,本文趁热打铁继续看一下AbstractQueuedSynchroni ...
- Condition实现等待、通知
使用Condition实现等待/通知: import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.L ...
- 十六、Condition等待通知
一.简介 我们可以使用syncronized和wait,notify实现等待通知.而syncronized的高级实现Lock,也可以实现等待通知,需要构造Condition的实例对象. JDK文档:h ...
- Lock接口之Condition接口
之前在写显示锁的是后,在显示锁的接口中,提到了new Condition这个方法,这个方法会返回一个Condition对象 简单介绍一下 Condition接口: 任意一个Java对象,都拥有一组监视 ...
- java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)
一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...
- 显式锁(四)Lock的等待通知机制Condition
任意一个Java对象,都拥有一组监视器方法(定义在根类Object上),主要包括:wait( ).wait(long timeout).notify().notifyAll()方法:这些方法与关 ...
- 使用Condition配合await()和signal()实现等待/通知
关键字Synchronized与wait()和notify()/notifyAll()结合可以实现“等待/通知”模式, Lock类的子类ReentrantLock也可以实现同样的功能,但需要借助Con ...
随机推荐
- c# 自定义控件之 ComboBox
winform 自带的 combobox 无法支持根据输入文本匹配列表中的项目,需要使用自定义控件. public class MyCombobox : ComboBox { //初始化数据项 pri ...
- BUUCTF weirdlist 一路到底
Weird list 这题恶心的一批 给了一堆列表 这...这是人做的题吗... 放飞自我,打开脑洞 把‘1’空出来,其他数字换为‘*’画出来 然后看到了flag,但是 这...这是什么flag,ag ...
- hdu 5435 A serious math problem
A serious math problem Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
- while循环与getopts处理
- 网络通信_socket
socket又称套接字 使用server实现循环通信 代码如下 import socket server = socket.socket() server.bind(()) server.listen ...
- JS匿名包装器(自执行匿名函数)
一.获得循环序号 for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { console.log(e); }, ...
- 多个ip地址获取
#include "stdafx.h"#include <stdio.h> #include <winsock.h> #include <window ...
- 【Database】MySQL实战45讲
01 | 基础架构:一条SQL查询语句是如何执行的? 1. MySQL 的基本架构图: MySQL可以分成: Server层 和 存储引擎层 两部分. Server层:包含连接器.查询缓存.分析器.优 ...
- logback-paycore.xml 日志配置
<?xml version="1.0" encoding="UTF-8"?><configuration> <property n ...
- 使用jxls导出Excel报表
导入jar包: <dependency> <groupId>net.sf.jxls</groupId> <artifactId>jxls-core< ...