Condition 的使用
Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。Condition的使用必须是在lock修饰的语句块中。
下面给出一个简单的示例:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by litao on 15/5/26.
*/
public class TaskTest {
private boolean flag;
private int num;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void sub() {
lock.lock();
while (flag == false) {
try {
condition.await();
} catch (Exception e) {
e.printStackTrace();
}
}
for (int i = 0; i < 5; i++) {
num--;
System.out.println("sub num:" + num);
}
flag = false;
condition.signal();
lock.unlock();
}
public void add() {
lock.lock();
while (flag == true) {
try {
condition.await();
} catch (Exception e) {
e.printStackTrace();
}
}
for (int i = 0; i < 5; i++) {
num++;
System.out.println("add num:" + num);
}
flag = true;
condition.signal();
lock.unlock();
}
public static void main(String[] args) {
final TaskTest taskTest = new TaskTest();
Thread thread1 = new Thread() {
@Override
public void run() {
taskTest.sub();
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
taskTest.add();
}
};
thread1.start();
thread2.start();
}
}
执行结果:
add num:1
add num:2
add num:3
add num:4
add num:5
sub num:4
sub num:3
sub num:2
sub num:1
sub num:0
可以看出,condition.signal()和condition.await()在这种情况下和传统的notify,wait具有相同的功效。
既然condition提供的功能和传统的方法相同,那为啥还要有这个东东呢?下面介绍condition的独特的地方。
public class Buffer {
private Lock lock = new ReentrantLock();
private Condition readCondition = lock.newCondition();
private Condition writeCondition = lock.newCondition();
private LinkedList<String> buffers;
private int size = 0;
private int maxSize;
public Buffer(int maxSize) {
this.maxSize = maxSize;
buffers=new LinkedList<String>();
}
public String get() {
lock.lock();
while (size == 0) {
try {
readCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String tmp = buffers.poll();
size = size - 1;
System.out.println(Thread.currentThread().getName()+" ,get: "+tmp);
writeCondition.signalAll();
lock.unlock();
return tmp;
}
public void set(String str) {
lock.lock();
while (size == maxSize) {
try {
writeCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
buffers.offer(str);
size = size + 1;
System.out.println(Thread.currentThread().getName()+" ,set: "+str);
readCondition.signalAll();
lock.unlock();
}
}
上面代码使一个使用了Condition实现的的Buffer。
这里将写和读分别使用了writeCondition和readCondition,相较于传统的notify,主要的区别是:使用condition可以按条件唤醒不同的线程,当可读的时候只唤醒读线程,当可写的时候只唤醒写线程。这样,不会致使某个无关的线程被唤醒后,立即又被阻塞。可以提高程序的执行效率。
使用上面Buffer,实现的一个生产者-消费者模型
import java.util.Random;
/**
* Created by litao on 15/5/26.
* 生产者-消费者模型
*/
public class ProducerAndConsumer {
public static void main(String[] args) {
final String[] randomStr = {
"0asaswwdwdwdw",
"1aswswswdwdwdw",
"2asasaswwdwd",
"3asaswwdwd",
"4sdsdwwdwd"
};
final Buffer buffer = new Buffer(5);
final Producer producer = new Producer(buffer);
final Consumer consumer = new Consumer(buffer);
final Random random = new Random();
for (int i = 0; i < 10; i++) {
Thread thread1 = new Thread("producer" + i) {
@Override
public void run() {
int index = random.nextInt(5);
producer.produce(randomStr[index]);
}
};
thread1.start();
}
for (int i = 0; i < 10; i++) {
Thread thread = new Thread("consumer" + i) {
@Override
public void run() {
String str = consumer.consum();
System.out.println("str:" + str);
}
};
thread.start();
}
}
public static class Producer {
private Buffer buffer;
public Producer(Buffer buffer) {
this.buffer = buffer;
}
public void produce(String str) {
buffer.set(str);
}
}
public static class Consumer {
private Buffer buffer;
public Consumer(Buffer buffer) {
this.buffer = buffer;
}
public String consum() {
return buffer.get();
}
}
}
程序执行结果:
producer0 ,set: 0asaswwdwdwdw
producer1 ,set: 0asaswwdwdwdw
producer2 ,set: 0asaswwdwdwdw
producer3 ,set: 3asaswwdwd
producer4 ,set: 2asasaswwdwd
consumer0 ,get: 0asaswwdwdwdw
producer5 ,set: 4sdsdwwdwd
str:0asaswwdwdwdw
consumer1 ,get: 0asaswwdwdwdw
str:0asaswwdwdwdw
producer6 ,set: 0asaswwdwdwdw
consumer4 ,get: 0asaswwdwdwdw
str:0asaswwdwdwdw
producer8 ,set: 1aswswswdwdwdw
consumer5 ,get: 3asaswwdwd
str:3asaswwdwd
producer9 ,set: 4sdsdwwdwd
consumer2 ,get: 2asasaswwdwd
str:2asasaswwdwd
consumer3 ,get: 4sdsdwwdwd
str:4sdsdwwdwd
producer7 ,set: 0asaswwdwdwdw
consumer6 ,get: 0asaswwdwdwdw
str:0asaswwdwdwdw
consumer7 ,get: 1aswswswdwdwdw
str:1aswswswdwdwdw
consumer8 ,get: 4sdsdwwdwd
str:4sdsdwwdwd
consumer9 ,get: 0asaswwdwdwdw
str:0asaswwdwdwdw
Condition 的使用的更多相关文章
- java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)
一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...
- MySQL 优化之 ICP (index condition pushdown:索引条件下推)
ICP技术是在MySQL5.6中引入的一种索引优化技术.它能减少在使用 二级索引 过滤where条件时的回表次数 和 减少MySQL server层和引擎层的交互次数.在索引组织表中,使用二级索引进行 ...
- 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题
调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...
- 1229【MySQL】性能优化之 Index Condition Pushdown
转自http://blog.itpub.net/22664653/viewspace-1210844/ [MySQL]性能优化之 Index Condition Pushdown2014-07-06 ...
- 四、线程同步之Lock和Condition
Lock同步锁 Lock 在jdk1.5 提供了Lock以便执行同步操作,和synchronized不同的是Lock提供了显示的方法获取锁和释放锁.Lock提供了以下几个方法,请求和释放锁: voi ...
- 【Java并发系列04】线程锁synchronized和Lock和volatile和Condition
img { border: solid 1px } 一.前言 多线程怎么防止竞争资源,即防止对同一资源进行并发操作,那就是使用加锁机制.这是Java并发编程中必须要理解的一个知识点.其实使用起来还是比 ...
- druid sql黑名单 报异常 sql injection violation, part alway true condition not allow
最近使用druid,发现阿里这个连接池 真的很好用,可以监控到连接池活跃连接数 开辟到多少个连接数 关闭了多少个,对于我在项目中查看错误 问题,很有帮助, 但是最近发现里面 有条sql语句 被拦截了, ...
- 【Java并发编程实战】-----“J.U.C”:Condition
在看Condition之前,我们先来看下面这个例子: 工厂类,用来存放.取出商品: public class Depot { private int depotSize; //仓库大小 private ...
- 【JAVA并发编程实战】12、使用condition实现多线程下的有界缓存先进先出队列
package cn.study.concurrency.ch14; import java.util.concurrent.locks.Condition; import java.util.con ...
- spring @condition 注解
spring @condition注解是用来在不同条件下注入不同实现的 demo如下: package com.foreveross.service.weixin.test.condition; im ...
随机推荐
- 获得Radio选中的后面文本框的值
例如: 选中的radio的值在button中显示 代码如下: <!DOCTYPE html> <html lang="en" xmlns="http:/ ...
- query 防止ajax重复提交
项目用到js了,首选jquery,能用库用库,原则. 碰到重复提交的问题,禁止住才行.百度google,还是Google给力. 知乎上有个高人,总结了四种,利用Jquery .post方法返回jqXH ...
- 多线程、Socket
多线程 线程.进程和应用程序域 进程:进程是一个操作系统上的概念,用来实现多任务并发执行,是资源分配的最小单元,各个进程是相互独立的,可以理解为执行当中的程序,在操作系统中一般用一个称为PCB的结 ...
- NFC手机
NFC手机 NFC手机内置NFC芯片,比原先仅作为标签使用的RFID更增加了数据双向传送的功能,这个进步使得其更加适合用于电子货币支付:特别是RFID所不能实现的,相互认证和动态加密以及一次性钥匙(O ...
- Jsp内置对象-session
session内置对象介绍 个人理解:session因为是唯一的, session是与请求有关的会话期,它是java.servlet.http.HttpSession类的对象,用来表示和存储当前页面的 ...
- 域名解析-delphi 源码
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, Syste ...
- oracle插入数据报错ORA-26026
今天进行数据清理时发现报错ORA-26026,主要是把从交易库提取数据并插入到归档库中. 检查一下发现是归档库的索引问题. 当时为了提高插入速度,所以删除了归档库的索引,可能对主键索引产生了影响. 解 ...
- IOS-图片上传到服务器
//获取document 路径- (NSString *)getDocumentPath{ NSArray *paths = NSSearchPathForDirectoriesInDomain ...
- Membership角色与权限管理
安全性:成员资格与角色:验证与授权. 一.建数据库:在VS工具中用DOS环境执行ASPNET_REGSQL 二.配置程序访问数据库: > 在web.config之中加入 <connecti ...
- nodejs框架express4.x 学习--安装篇
一.安装建立项目 1.安装nodejs 2.安装express(全局) npm install -g express 默认安装的是4.12.4 3.由于在3.6版本之后项目构建器被单独拆分出来,所以还 ...