您的位置:首页 > 其它

高并发学习之使用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();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: