高并发学习之使用Condition实现三个线程轮转&阻塞缓冲区

来源:互联网 发布:即时通讯软件开发方案 编辑:程序博客网 时间:2024/06/08 09:52
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();    }}

ConditionObject 监视器方法(waitnotifynotifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

条件(也称为条件队列条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像Object.wait 做的那样。

Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。

作为一个示例,假定有一个绑定的缓冲区,它支持 puttake 方法。如果试图在空的缓冲区上执行 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();     }   }  }



0 0
原创粉丝点击