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 ...
随机推荐
- 基于keepalived对redis做高可用配置---转载
关于keepalived的详细介绍,请移步本人相关博客:http://wangfeng7399.blog.51cto.com/3518031/1405785 功能 ip地址 安装软件 主redis 1 ...
- Java Stax操作XML简介
使用stax操作xml 非常的简单,它的读取过程像是一个光标在移动.针对不同的节点做不同的处理. 先看一个基于光标的模型处理xml: public class StaxTest { @Test pub ...
- Bash判断文件是否存在
#!/bin/bash if [ -f filename ]; then echo 'file exist' else echo 'file not exist' fi
- LCA问题
基本概念 LCA:树上的最近公共祖先,对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. RMQ:区间最小值查询问题.对于长度为n的 ...
- jquery中Live方法不可用,Jquery中Live方法失效
jquery中Live方法不可用,Jquery中Live方法失效 >>>>>>>>>>>>>>>>> ...
- JS关闭窗口或JS关闭页面的几种代码
//JS定时自动关闭窗口 <script language="javascript"> <!-- function closewin(){ self.opener ...
- C语言malloc()函数:动态分配内存空间
头文件:#include <stdlib.h> malloc() 函数用来动态地分配内存空间(如果你不了解动态内存分配,请查看:C语言动态内存分配及变量存储类别),其原型为:void* m ...
- Delphi OO
深入Delphi编程(OOP) 日期:2007年11月9日 作者:左轻侯 人气: 2595 查看:[大字体 中字体 小字体] 刚刚接触的Delphi的朋友,可能最感兴趣的就是它丰富.强大的VCL(可视 ...
- 如何在swift中实现oc中的分类
在oc中为了增强已有类的功能,我们经常使用分类.使用分类,我们可以在不破坏原有类的结构的前提下,对原有类进行模块化的扩展. 但是在swift中没有分类这种写法了.相对应的是swift中只有扩展(Ext ...
- java中的包装类
每一个包装类都对应一种基本数据类型.包装类有:Integer.character.Byte.Short.Long.Floot.Double.Boolean这八种,分别对应的基本数据类型是:int.ch ...