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 ...
随机推荐
- 50.Maximal Square(最大正方形)
Level Medium 题目描述: Given a 2D binary matrix filled with 0's and 1's, find the largest square conta ...
- 重读ORB_SLAM之LocalMapping线程难点
1. 认清几个锁与布尔参数 线程的通信与相互影响在ORB比较复杂,需要好好缕清思路. 1.1 mbStopRequested,由RequestStop函数设定,主要是在回环线程里,在运行全局优化时,以 ...
- Hibernate4教程二:基本配置
可编程的配置方式一: 如果在配置cfg.xml的时候,不想在里面配置hbm.xml怎么办呢?可在程序里使用可编程的配置方式,也就是使用程序来指定在cfg.xml里面的配置信息,不推荐这种方式.如下: ...
- 点击td对同行的其他td进行操作
假设有这样的一段tr: <tr> <td><input type="checkbox" name="item" class=&qu ...
- 笔记78 HttpStatus
HttpStatus = { //Informational 1xx 信息 '100' : 'Continue', //继续 '101' : 'Switching Protocols', //交换协议 ...
- Hibernate中Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法有什么区别?
Hibernate的对象有三种状态:瞬态.持久态和游离态.游离状态的实例可以通过调用save().persist()或者saveOrUpdate()方法进行持久化:脱管状态的实例可以通过调用 upda ...
- 备份Oracle 数据库。
#!/bin/bash# 2018-07-07 oracle database back#filename=`date +%Y%m%d`filename=`date +%Y_%m_%d_%H%M`di ...
- springmvc.xml标配配置
这里提供配置模板[绝不会多余]: <context:component-scan base-package="com.atguigu"></context:com ...
- mybatis generator 生成的example类的使用方法
generator 生成的example类 示例 1. 搜索数据库Id不为空打元组 java代码 @RequestMapping("/test") public String ex ...
- Windows下JDK安装步骤 + eclipse集成配置
一.JDK环境配置 1.解压到java目录下 2.路径和上面路径一致 3.配置path路径 4.查看版本 二.Eclipse配置 1.编译版本 2.运行环境 3.默认字集 4.字体大小