高并发学习之使用Condition实现三个线程轮转&阻塞缓冲区
2016-01-25 16:43
239 查看
package com.lei.lock;/* *@author leixingbang_sx *Mail:leixingbang_sx@qiyi.com *@create 2016/1/25 16:11 *desc */ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ThreeBoys { private Lock lock= new ReentrantLock(); private Condition c1=lock.newCondition(); private Condition c2=lock.newCondition(); private Condition c3=lock.newCondition(); public static final int SEQ_First=1; public static final int SEQ_Second=2; public static final int SEQ_Third=3; public static int seq=1; public void doFirst(){ try { lock.lock(); while(seq!=SEQ_First) this.c1.await(); for(int i=1;i<=5;i++) { System.out.println("线程:"+Thread.currentThread().getName()+"做第:"+i+"次"); Thread.sleep(500); } seq=SEQ_Second;//置为2让第二个线程可以执行 c2.signal(); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public void doSecond(){ try { lock.lock(); while(seq!=SEQ_Second) this.c2.await(); for(int i=1;i<=10;i++) { System.out.println("线程:"+Thread.currentThread().getName()+"做第:"+i+"次"); Thread.sleep(500); } seq=SEQ_Third;//置为3让第3个线程可以执行 c3.signal(); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public void doThird(){ try { lock.lock(); while(seq!=SEQ_Third) this.c3.await(); for(int i=1;i<=15;i++) { System.out.println("线程:"+Thread.currentThread().getName()+"做第:"+i+"次"); Thread.sleep(500); } seq=SEQ_First;//置为1让第1个线程可以执行 c1.signal(); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public static void main(String[] args) { final ThreeBoys tb=new ThreeBoys(); new Thread( new Runnable() { @Override public void run() { while (true) { tb.doFirst(); } } } ).start(); new Thread( new Runnable() { @Override public void run() { while (true) { tb.doSecond(); } } } ).start(); new Thread( new Runnable() { @Override public void run() { while (true) { tb.doThird(); } } } ).start(); } }
Condition将
Object监视器方法(
wait、
notify和
notifyAll)分解成截然不同的对象,以便通过将这些对象与任意
Lock实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,
Lock替代了
synchronized方法和语句的使用,
Condition替代了 Object 监视器方法的使用。
条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像
Object.wait做的那样。
Condition实例实质上被绑定到一个锁上。要为特定
Lock实例获得
Condition实例,请使用其
newCondition()方法。
作为一个示例,假定有一个绑定的缓冲区,它支持
put和
take方法。如果试图在空的缓冲区上执行
take操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行
put操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存
put线程和
take线程,这样就可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程。可以使用两个
Condition实例来做到这一点。
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
相关文章推荐
- error C2143: syntax error : missing ';' before 'type'
- Protocol Buffers 的 ActionScript 3 编译器
- 通宵教室
- Java异常处理--将try/catch区段置于循环之外
- pthread_create创建线程后必须使用join或detach释放线程资源[内存泄漏]
- JVM学习笔记十一 之 编译期优化和运行期优化
- 各类 C++ hashmap 性能测试总结
- float和double类型的内存分布
- 更好更快更高效解析JSON说明[json-c]
- C++结构体实例和类实例的初始化
- windows socket select非阻塞实例
- 在非控制台程序中打印出printf
- [VC]setsockopt 设置socket 详细用法(超时、非阻塞等)
- 如何将动态链接库(C++ DLL)中的printf显示在其被调用的程序控制台上
- Android NDK Build 参数
- appledoc格式
- 【慕课笔记】U1 类和对象 第3节 如何使用JAVA中的对象
- cocos2dx-lua捕获用户touch事件的几种方式
- 将word文档A表格中的内容拷贝到word文档B表格中
- Java异常处理--将try/catch区段置于循环之外