廖雪峰Java11多线程编程-3高级concurrent包-3Condition
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的更多相关文章
- 廖雪峰Java11多线程编程-3高级concurrent包-5Atomic
Atomic java.util.concurrent.atomic提供了一组原子类型操作: 如AtomicInteger提供了 int addAndGet(int delta) int increm ...
- 廖雪峰Java11多线程编程-3高级concurrent包-4Concurrent集合
Concurrent 用ReentrantLock+Condition实现Blocking Queue. Blocking Queue:当一个线程调用getTask()时,该方法内部可能让给线程进入等 ...
- 廖雪峰Java11多线程编程-3高级concurrent包-1ReentrantLock
线程同步: 是因为多线程读写竞争资源需要同步 Java语言提供了synchronized/wait/notify来实现同步 编写多线程同步很困难 所以Java提供了java.util.concurre ...
- 廖雪峰Java11多线程编程-3高级concurrent包-6ExecutorService
Java语言内置多线程支持: 创建线程需要操作系统资源(线程资源,栈空间) 频繁创建和销毁线程需要消耗大量时间 如果可以复用一个线程 线程池: 线程池维护若干个线程,处于等待状态 如果有新任务,就分配 ...
- 廖雪峰Java11多线程编程-3高级concurrent包-9Fork_Join
线程池可以高效执行大量小任务: Fork/Join线程池可以执行一种特殊的任务: 把一个大任务拆成多个小任务并行执行 Fork/Join是在JDK 1.7引入的 示例:计算一个大数组的和 Fork/J ...
- 廖雪峰Java11多线程编程-3高级concurrent包-8CompletableFuture
使用Future可以获得异步执行结果 Future<String> future = executor.submit(task); String result = future.get() ...
- 廖雪峰Java11多线程编程-3高级concurrent包-7Future
JDK提供了ExecutorService接口表示线程池,可以通过submit提交一个任务. ExecutorService executor = Executors.newFixedThreadPo ...
- 廖雪峰Java11多线程编程-3高级concurrent包-2ReadWriteLock
ReentrantLock保证单一线程执行 ReentrantLock保证了只有一个线程可以执行临界区代码: 临界区代码:任何时候只有1个线程可以执行的代码块. 临界区指的是一个访问共用资源(例如:共 ...
- 廖雪峰Java11多线程编程-2线程同步-3死锁
1.线程锁可以嵌套 在多线程编程中,要执行synchronized块: 必须首先获得指定对象的锁 Java的线程锁是可重入的锁.对同一个对象,同一个线程,可以多次获取他的锁,即同一把锁可以嵌套.如以下 ...
随机推荐
- 第37讲 谈谈Spring Bean的生命周期和作用域
在企业应用软件开发中,Java 是毫无争议的主流语言,开放的 Java EE 规范和强大的开源框架功不可没,其中 Spring 毫无疑问已经成为企业软件开发的事实标准之一.今天这一讲,我将补充 Spr ...
- Docker Api 实测
好久没写博客,工作中想着未来部门需要对docker进行维护相对麻烦,而且,网络上也缺少一些合适的项目,于是准备筹划自己动手.先找到了Docker 的API文档,地址是:https://docs.doc ...
- MySQL基础管理
1.用户管理 1.用户的作用: 登录:管理相对应的库表 2.定义 定义用户名和白名单 all@'10.0.0.%' 命名用户名时,最好不要太长,要和业务相关 白名单类型: user@'10.0.0.5 ...
- json-lib 的maven dependency 一直找不到jar 包
项目中要用到json-lib,mvnrepository.com查找它的dependency时结果如下: xml 代码 <dependency> <groupId>net.sf ...
- ajax 接收json数据的进一步了解
var url = "../searchclasses"; $.ajax({ url: url, type: "post", dataType: "j ...
- CentOS7开放防火墙端口
~~~~~~~~~~~~开放某个端口~~~~~~~~~~~~firewall-cmd --zone=public --add-port=6669/tcp --permanentfirewall-cmd ...
- Python 执行tail文件并操作
def log_search(self, logfile, search_content, timeout=10): import time import subprocess import sele ...
- Linux 常用命令:文本查看篇
前言 Linux常用命令中,除了cat还有很多其他用于文本查看的命令.本文将简单介绍一下这些文本查看的命令. 全文本显示--cat cat可能是常用的一个文本查看命令了,使用方法也很简单: cat f ...
- 2019 Multi-University Training Contest 3 B 支配树
题目传送门 题意:给出衣服有向无环图(DAG),,定义出度为0的点为中心城市,每次询问给出两个点,求破坏任意一个城市,使得这两个点至少有一个点无法到达中心城市,求方案数. 思路:首先建立反向图,将城市 ...
- python对urlEncode进行解码
利用python自带的urlib进行编码和解码,没有什么问题.(https://www.hustyx.com/python/) 但如果是用url编码工具(http://tool.chinaz.com/ ...