• 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实现等待通知的更多相关文章

  1. 再谈AbstractQueuedSynchronizer:共享模式与基于Condition的等待/通知机制实现

    共享模式acquire实现流程 上文我们讲解了AbstractQueuedSynchronizer独占模式的acquire实现流程,本文趁热打铁继续看一下AbstractQueuedSynchroni ...

  2. 再谈AbstractQueuedSynchronizer2:共享模式与基于Condition的等待/通知机制实现

    共享模式acquire实现流程 上文我们讲解了AbstractQueuedSynchronizer独占模式的acquire实现流程,本文趁热打铁继续看一下AbstractQueuedSynchroni ...

  3. Java 并发编程-再谈 AbstractQueuedSynchronizer 2:共享模式与基于 Condition 的等待 / 通知机制实现

    共享模式acquire实现流程 上文我们讲解了AbstractQueuedSynchronizer独占模式的acquire实现流程,本文趁热打铁继续看一下AbstractQueuedSynchroni ...

  4. Condition实现等待、通知

    使用Condition实现等待/通知: import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.L ...

  5. 十六、Condition等待通知

    一.简介 我们可以使用syncronized和wait,notify实现等待通知.而syncronized的高级实现Lock,也可以实现等待通知,需要构造Condition的实例对象. JDK文档:h ...

  6. Lock接口之Condition接口

    之前在写显示锁的是后,在显示锁的接口中,提到了new Condition这个方法,这个方法会返回一个Condition对象 简单介绍一下 Condition接口: 任意一个Java对象,都拥有一组监视 ...

  7. java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)

    一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...

  8. 显式锁(四)Lock的等待通知机制Condition

       任意一个Java对象,都拥有一组监视器方法(定义在根类Object上),主要包括:wait( ).wait(long timeout).notify().notifyAll()方法:这些方法与关 ...

  9. 使用Condition配合await()和signal()实现等待/通知

    关键字Synchronized与wait()和notify()/notifyAll()结合可以实现“等待/通知”模式, Lock类的子类ReentrantLock也可以实现同样的功能,但需要借助Con ...

随机推荐

  1. Visual Studio Code如何编写运行C、C++

    Visual Studio Code如何编写运行C.C++ 作者:知乎用户链接:https://www.zhihu.com/question/30315894/answer/154979413来源:知 ...

  2. mySQL部分疑问和小结(orale)

    2015/10/15 1.mysql语句: ALTER table scfz_xewp add BGR varchar(255) after KYR 2.创建触发器时:  --/   CREATE D ...

  3. Python3学习笔记——类

    #!/usr/bin/env python #-*- coding:utf-8 -*- #面向对象(类+对象) 三大特性:封装.继承.多态 类的成员: 字段: 普通字段:保存在对象(实例)中,执行只能 ...

  4. Flask配置方法

    flask应用的配置(使用uWSGI和Nginx在CentOS 7上搭建) 基础的Nginx 数据库等配置省略 创建python虚拟环境 sudo pip install virtualenv mkd ...

  5. redis与mysql一致性方案解析

    一 前言 首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用.在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作 但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存 ...

  6. Git中.gitignore文件不起作用

    Git中.gitignore文件不起作用的解决以及Git中的忽略规则介绍   在Studio里使用Git管理代码的过程中,可以修改.gitignore文件中的标示的方法来忽略开发者想忽略掉的文件或目录 ...

  7. 常用的外网yum源之epel.repo

    [epel]name=Extra Packages for Enterprise Linux 6 - $basearchbaseurl=http://download.fedoraproject.or ...

  8. Tornado中异步框架的使用

    tornado的同步框架与其他web框架相同都是处理先来的请求,如果先来的请求阻塞,那么后面的请求也会处理不了.一直处于等待过程中.但是请求一旦得到响应,那么: 请求发送过来后,将需要的本站资源直接返 ...

  9. CF963E Circles of Waiting

    Circles of Waiting 求一个整点四连通随机游⾛,离原点距离超过R期望步数.R≤50. 带状矩阵法 本质上就是网格图的随机游走. \[ E_x=\sum_y P_{x,y}E_y+1 \ ...

  10. vue video全屏播放

    需求: 1.视频为长方形,页面初始化打开为横屏全屏播放视频. 2.微信不支持自动播放,故自动播放需求删除. 方法: 1.vue-video-player插件 因需求较简单,仅要求播放本地一个视频,故未 ...