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 的使用的更多相关文章

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

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

  2. MySQL 优化之 ICP (index condition pushdown:索引条件下推)

    ICP技术是在MySQL5.6中引入的一种索引优化技术.它能减少在使用 二级索引 过滤where条件时的回表次数 和 减少MySQL server层和引擎层的交互次数.在索引组织表中,使用二级索引进行 ...

  3. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

  4. 1229【MySQL】性能优化之 Index Condition Pushdown

    转自http://blog.itpub.net/22664653/viewspace-1210844/  [MySQL]性能优化之 Index Condition Pushdown2014-07-06 ...

  5. 四、线程同步之Lock和Condition

    Lock同步锁 Lock 在jdk1.5  提供了Lock以便执行同步操作,和synchronized不同的是Lock提供了显示的方法获取锁和释放锁.Lock提供了以下几个方法,请求和释放锁: voi ...

  6. 【Java并发系列04】线程锁synchronized和Lock和volatile和Condition

    img { border: solid 1px } 一.前言 多线程怎么防止竞争资源,即防止对同一资源进行并发操作,那就是使用加锁机制.这是Java并发编程中必须要理解的一个知识点.其实使用起来还是比 ...

  7. druid sql黑名单 报异常 sql injection violation, part alway true condition not allow

    最近使用druid,发现阿里这个连接池 真的很好用,可以监控到连接池活跃连接数 开辟到多少个连接数 关闭了多少个,对于我在项目中查看错误 问题,很有帮助, 但是最近发现里面 有条sql语句 被拦截了, ...

  8. 【Java并发编程实战】-----“J.U.C”:Condition

    在看Condition之前,我们先来看下面这个例子: 工厂类,用来存放.取出商品: public class Depot { private int depotSize; //仓库大小 private ...

  9. 【JAVA并发编程实战】12、使用condition实现多线程下的有界缓存先进先出队列

    package cn.study.concurrency.ch14; import java.util.concurrent.locks.Condition; import java.util.con ...

  10. spring @condition 注解

    spring @condition注解是用来在不同条件下注入不同实现的 demo如下: package com.foreveross.service.weixin.test.condition; im ...

随机推荐

  1. 3 Ways of JDK Source Code Attachment in Eclipse---reference

    You wanna look at a JVM class while you are coding and you cannot. Here is the solution. First of al ...

  2. DevExpress的GridView设置特定行的样式

    GridView控件绑定事件: gridView_SampleData.CustomDrawCell += gridView_SampleData_CustomDrawCell; 根据自定义逻辑来改变 ...

  3. VC/MFC强制退出本进程自己,VC/MFC关闭自己

    正常情况下通过关闭主窗口close或发送PostQuitMessage(WM_QUIT);消息 能关闭窗口.但如果一个进程中包括多个子线程当子线程没有结束还占用 系统资源时通过上面的两种方法是不能立即 ...

  4. php 白屏

    访问php白屏(base on lnmp) vim nginx/conf/fastcgi_param fastcgi_param REDIRECT_STATUS 200; fastcgi_param ...

  5. 在ASP.NET中ShowModalDialog+ztree的使用

    .aspx: <script type="text/javascript"> function getReturnValue() { var strResult = w ...

  6. DEDE自带的采集功能,标题太短的解决方法

    DEDE自带的采集功能,标题太短获取不全的解决方法搜索了好多之后,终于还是在dede的官方论坛找到了答案.增加采集标题长度:255  目的:原标题长度太小,影响文件采集⑴修改系统参数设置(文档标题最大 ...

  7. 日志记录组件[Log4net]详细介绍

    转载:http://www.cnblogs.com/liwei6797/archive/2007/04/27/729679.html 因为工作中有要用到Log记录,找到一篇不错的文章,就转了过来. 一 ...

  8. 2.RABBITMQ 入门 - WINDOWS - 生产和消费消息 一个完整案例

    关于安装和配置,见上一篇 1.RABBITMQ 入门 - WINDOWS - 获取,安装,配置 公司有需求,要求使用winform开发这个东西(消息中间件),另外还要求开发一个日志中间件,但是也是要求 ...

  9. C# Ref 与out 的区别

    在C#中,有四种传递参数方式: 1. 传值 (value) : 无额外修饰符 2. 传址(reference) : 需修饰符Ref,传入函数的参数必须先赋值 3. 输出参数(output): 需修饰符 ...

  10. oracle模糊查询效率提高

    1.使用两边加‘%’号的查询,oracle是不通过索引的,所以查询效率很低. 例如:select count(*) from lui_user_base t where t.user_name lik ...