1.Condition实现等待和唤醒线程

java.util.locks.ReentrantLock用于替代synchronized加锁



但是synchronized可以使用wait和notify实现线程在条件不满足时的等待,条件满足时的唤醒。

如何使用ReentrantLock实现wait/notify的功能?

这个时候我们可以使用Condition对象来实现条件不满足时的等待,条件满足时的唤醒。

class TaskQueue{
final Lock lock = new ReentrantLock()
final Condition notEmpty = lock.newCondition();
}

1.1 对Condition对象调用await()方法就相当于对所对象调用wait()方法。


### 1.2 对Condition对象调用signalAll()就相当于在synchronized加锁对象调用notifyAll()方法。

Condition.await/signal/signalAll原理和wait/notify/notifyAll一致
* await()会释放当前锁,进入等待状态
* signal()会唤醒某个等待线程
* signalAll()会唤醒所有等待线程
* 唤醒线程从await()返回后需要重新获得锁

2. 示例

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; class TaskQueue{
final Queue<String> queue = new LinkedList<>();
final Lock lock = new ReentrantLock();
final Condition notEmpty = lock.newCondition();
public String getTask() throws InterruptedException{
lock.lock();
try{
while(this.queue.isEmpty()){
notEmpty.await();
}
return queue.remove();
}finally {
lock.unlock();
}
}
public void addTask(String name){
lock.lock();
try{
this.queue.add(name);
notEmpty.signalAll();
}finally {
lock.unlock();
}
}
}
class WorkerThread extends Thread{
TaskQueue taskQueue;
public WorkerThread(TaskQueue taskQueue){
this.taskQueue = taskQueue;
}
public void run(){
while(!isInterrupted()){
String name;
try{
name = taskQueue.getTask();
}catch (InterruptedException e){
break;
}
String result = "Hello, "+name+" !";
System.out.println(result);
}
}
}
public class Main{
public static void main(String[] args) throws InterruptedException{
TaskQueue taskQueue = new TaskQueue();
WorkerThread worker = new WorkerThread(taskQueue);
worker.start();
taskQueue.addTask("Bob");
Thread.sleep(1000);
taskQueue.addTask("Alice");
Thread.sleep(1000);
taskQueue.addTask("Tim");
Thread.sleep(1000);
worker.interrupt();
worker.join();
System.out.println("END");
}
}


## 3. 总结
使用ReentrantLock+Condition可以更安全的实现线程的同步、等待和唤醒。
* Condition可以替代wait/notify
* Condition对象必须从ReentrantLock对象获取
* ReentrantLock+Condition可以替代synchronized+wait/notify

廖雪峰Java11多线程编程-3高级concurrent包-3Condition的更多相关文章

  1. 廖雪峰Java11多线程编程-3高级concurrent包-5Atomic

    Atomic java.util.concurrent.atomic提供了一组原子类型操作: 如AtomicInteger提供了 int addAndGet(int delta) int increm ...

  2. 廖雪峰Java11多线程编程-3高级concurrent包-4Concurrent集合

    Concurrent 用ReentrantLock+Condition实现Blocking Queue. Blocking Queue:当一个线程调用getTask()时,该方法内部可能让给线程进入等 ...

  3. 廖雪峰Java11多线程编程-3高级concurrent包-1ReentrantLock

    线程同步: 是因为多线程读写竞争资源需要同步 Java语言提供了synchronized/wait/notify来实现同步 编写多线程同步很困难 所以Java提供了java.util.concurre ...

  4. 廖雪峰Java11多线程编程-3高级concurrent包-6ExecutorService

    Java语言内置多线程支持: 创建线程需要操作系统资源(线程资源,栈空间) 频繁创建和销毁线程需要消耗大量时间 如果可以复用一个线程 线程池: 线程池维护若干个线程,处于等待状态 如果有新任务,就分配 ...

  5. 廖雪峰Java11多线程编程-3高级concurrent包-9Fork_Join

    线程池可以高效执行大量小任务: Fork/Join线程池可以执行一种特殊的任务: 把一个大任务拆成多个小任务并行执行 Fork/Join是在JDK 1.7引入的 示例:计算一个大数组的和 Fork/J ...

  6. 廖雪峰Java11多线程编程-3高级concurrent包-8CompletableFuture

    使用Future可以获得异步执行结果 Future<String> future = executor.submit(task); String result = future.get() ...

  7. 廖雪峰Java11多线程编程-3高级concurrent包-7Future

    JDK提供了ExecutorService接口表示线程池,可以通过submit提交一个任务. ExecutorService executor = Executors.newFixedThreadPo ...

  8. 廖雪峰Java11多线程编程-3高级concurrent包-2ReadWriteLock

    ReentrantLock保证单一线程执行 ReentrantLock保证了只有一个线程可以执行临界区代码: 临界区代码:任何时候只有1个线程可以执行的代码块. 临界区指的是一个访问共用资源(例如:共 ...

  9. 廖雪峰Java11多线程编程-2线程同步-3死锁

    1.线程锁可以嵌套 在多线程编程中,要执行synchronized块: 必须首先获得指定对象的锁 Java的线程锁是可重入的锁.对同一个对象,同一个线程,可以多次获取他的锁,即同一把锁可以嵌套.如以下 ...

随机推荐

  1. (转)VS2010-MFC编程入门教程之目录和总结

     目前该教程可以到鸡啄米编程课堂去学习,阅读体验更好,更适合在线学习. 原文目录及链接: 一.VS2010/MFC编程入门教程之目录 第一部分:VS2010/MFC开发环境 VS2010/MFC编程入 ...

  2. 2019 牛客多校第三场 H Magic Line

    题目链接:https://ac.nowcoder.com/acm/contest/883/H 题目大意 给定 N 个不同的整数点,N 为偶数,求一条直线,这条直线能把这 N 个点对半分开,输出这条直线 ...

  3. CodeForces 1166D Cute Sequences

    题目链接:http://codeforces.com/problemset/problem/1166/D 题目大意 给定序列的第一个元素 a 和最后一个元素 b 还有一个限制 m,请构造一个序列,序列 ...

  4. 剑指offer——32从上到下打印二叉树

    题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印.   题解: 就是简单的层序遍历 class Solution { public: vector<int> PrintFro ...

  5. SolrCloud6.1.0之SQL查询测试

    Solr发展飞快,现在最新的版本已经6.1.0了,下面来回顾下Solr6.x之后的一些新的特点: (1)并行SQL特性支持,编译成Streaming 表达式,可以在solrcloud集群中,并行执行  ...

  6. 判断APP是否已安装

    NSString *str = [NSString stringWithFormat:@"%@://%@",[dic objectForKey:@"ios_url_sch ...

  7. mysql双主热备

    先搭建mysql主从模式,主从请参考mysql 主从笔记 然后在在配置文件里添加如下配置 1 log_slave_updates= #双主热备的关键参数.默认情况下从节点从主节点中同步过来的修改事件是 ...

  8. 关于maven工程将model删除重建之后变为灰色的问题的解决

    问题描述: IDEA中的maven工程中有时候将model或者子model建错,删除之后,子模块在maven在侧栏的maven projects中是灰色的,而且是并没有依赖父工程 在网上搜了搜解决办法 ...

  9. IDEA被删除的模块在编译时会再次出现

    工程根目录下.idea文件->compiler.xml,删除多余的model,workspace.xml->删除带有无用的target标签

  10. javascript和jquery

    JavaScript 1.概述 JavaScript是一种基于对象和事件驱动,并具有安全性能的脚本语言. 2.语法 HTML 中的脚本必须位于 <script> 与 </script ...