凤凰平台注册开户_凤凰彩票app下载安装_凤凰彩票投注网

热门关键词: 凤凰平台注册开户,凤凰彩票app下载安装,凤凰彩票投注网

java并发编制程序之Condition凤凰彩票app下载安装:

作者: 编程知识  发布:2019-09-26

先做总结:

此篇博客所有源码均来自JDK 1.8

引言


在java中,对于任意一个java对象,它都拥有一组定义在java.lang.Object上监视器方法,包括wait()wait(long timeout)notify()notifyAll(),这些方法配合synchronized关键字一起使用可以实现等待/通知模式。

同样,Condition接口也提供了类似Object监视器的方法,通过与Lock配合来实现等待/通知模式。

为了更好的了解Condition的特性,我们来对比一下两者的使用方式以及功能特性:

对比项 Object监视器 Condition
前置条件 获取对象的锁 调用Lock.lock获取锁,调用Lock.newCondition获取Condition对象
调用方式 直接调用,比如object.notify() 直接调用,比如condition.await()
等待队列的个数 一个 多个
当前线程释放锁进入等待状态 支持 支持
当前线程释放锁进入等待状态,在等待状态中不断响中断 不支持 支持
当前线程释放锁并进入超时等待状态 支持 支持
当前线程释放锁并进入等待状态直到将来的某个时间 不支持 支持
唤醒等待队列中的一个线程 支持 支持
唤醒等待队列中的全部线程 支持 支持

1、为什么使用Condition条件?

synchronized配合Object的wait()、notify()系列方法可以实现等待/通知模式。

Lock提供了条件Condition,对线程的等待、唤醒操作更加详细和灵活。

Condition的作用是对锁进行更精确的控制。Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法。

在没有Lock之前,我们使用synchronized来控制同步,配合Object的wait()、notify()系列方法可以实现等待/通知模式。在Java SE5后,Java提供了Lock接口,相对于Synchronized而言,Lock提供了条件Condition,对线程的等待、唤醒操作更加详细和灵活。下图是Condition与Object的监视器方法的对比(摘自《Java并发编程的艺术》):

Condition使用示例


实现一个简单的有界队列,队列为空时,队列的删除操作将会阻塞直到队列中有新的元素,队列已满时,队列的插入操作将会阻塞直到队列出现空位。

凤凰彩票app下载安装 1

简单有界队列实现

不难看出,Condition的使用方式是比较简单的,需要注意的是使用Condition的等待/通知需要提前获取到与Condition对象关联的锁,Condition对象由Lock对象创建。

以上述示例中的add(T object)为例,详细描述一下Condition等待/通知的整个过程:

  • 获取锁,确保对数据数据修改的安全性;
  • 数组元素的个数等于数组的长度时,调用notFull.await(),插入线程释放锁进入等待;
  • 数组未满,添加元素到数组中,调用notEmpty.signal()通知等待在notEmpty上的线程,数组中有新的元素可以操作。

总的来说,Condition的等待/通知使用方式大体上跟经典的Object监视器上的等待/通知是非常类似的。

2、Condition条件实现原理:

lock.newCondition(),new一个ConditionObject对象,ConditionObject有一个单向等待队列

condition等待队列:线程已经拿到锁,但是因为不满足某个条件,被放入等待队列并释放锁,不能获取锁

   AQS同步队列:线程抢锁失败,被放入AQS阻塞队列,等前面线程释放锁之后自己再获取锁

:当前线程T加入条件等待队列 释放锁 park()当前线程

  signal():当前线程T节点出条件等待队列 T节点加入AQS同步队列 unpark()T线程

凤凰彩票app下载安装 2

Condition实现分析


一、Condition实现生产者消费者问题

class BoundedBuffer {    final Lock lock = new ReentrantLock();    // condition 依赖于 lock 来产生    final Condition notFull = lock.newCondition();    final Condition notEmpty = lock.newCondition();    final Object[] items = new Object[100];    int putptr, takeptr, count;    // 生产    public void put throws InterruptedException {        lock.lock();        try {            while (count == items.length)                notFull.await();  // 队列已满,等待,直到 not full 才能继续生产            items[putptr] = x;            if (++putptr == items.length) putptr = 0;            ++count;            notEmpty.signal(); // 生产成功,队列已经 not empty 了,发个通知出去        } finally {            lock.unlock();        }    }    // 消费    public Object take() throws InterruptedException {        lock.lock();        try {            while (count == 0)                notEmpty.await(); // 队列为空,等待,直到队列 not empty,才能继续消费            Object x = items[takeptr];            if (++takeptr == items.length) takeptr = 0;            --count;            notFull.signal(); // 被我消费掉一个,队列 not full 了,发个通知出去            return x;        } finally {            lock.unlock();        }    }}

Condition

Condition api

Condition提供以下接口以供实现:

  1. void await() throws InterruptedException
    当前线程进入等待状态,直到被通知(signal)或者被中断时,当前线程进入运行状态,从await()返回;

  2. void awaitUninterruptibly()
    当前线程进入等待状态,直到被通知,对中断不做响应;

  3. long awaitNanos(long nanosTimeout) throws InterruptedException
    在接口1的返回条件基础上增加了超时响应,返回值表示当前剩余的时间,如果在nanosTimeout之前被唤醒,返回值 = nanosTimeout - 实际消耗的时间,返回值 <= 0表示超时;

  4. boolean await(long time, TimeUnit unit) throws InterruptedException
    同样是在接口1的返回条件基础上增加了超时响应,与接口3不同的是:

  • 可以自定义超时时间单位;
  • 返回值返回true/false,在time之前被唤醒,返回true,超时返回false。
  1. boolean awaitUntil(Date deadline) throws InterruptedException
    当前线程进入等待状态直到将来的指定时间被通知,如果没有到指定时间被通知返回true,否则,到达指定时间,返回false;

  2. void signal()
    唤醒一个等待在Condition上的线程;

  3. void signalAll()
    唤醒等待在Condition上所有的线程。

二、lock与condition关系

    // 一个lock可以new多个条件    public static void main(String[] args) {        ReentrantLock lock = new ReentrantLock();        lock.lock();        Condition newCondition1 = lock.newCondition();        newCondition1.await();        newCondition1.signal();        Condition newCondition2 = lock.newCondition();        newCondition2.await();        newCondition2.signal();        lock.unlock();    }    // ReentrantLock.newCondition()    public Condition newCondition() {        return sync.newCondition();    }        // ReentrantLock.Sync.newCondition()    final ConditionObject newCondition() {        return new ConditionObject();    }

Condition提供了一系列的方法来对阻塞和唤醒线程:

Condition具体实现分析

ConditionObject是Condition在java并发中的具体的实现,它是AQS的内部类。因为Condition相关操作都需要获取锁,所以作为AQS的内部类也比较合理。接下来就以ConditionObject的等待队列、等待、通知为切入点分析ConditionObject的具体实现。

三、条件队列

每个Condition对象都包含着一个FIFO队列,该队列是Condition对象通知/等待功能的关键。在队列中每一个节点(使用的AQS的节点)都包含着一个线程引用,该线程就是在该Condition对象上等待的线程。

public class ConditionObject implements Condition, java.io.Serializable {    private static final long serialVersionUID = 1173984872572414699L;    private transient Node firstWaiter; //头节点    private transient Node lastWaiter; //尾节点    public ConditionObject() {    }        /**     * 通过addConditionWaiter()方法理解等待队列数据结构     * 将当前线程加入条件等待队列     * 1.Node就是AQS的Node     * 2.单向链表,通过nextWaiter连接     * 3.waitStatus==Node.CONDITION才能在等待队列中     */    private Node addConditionWaiter() {        Node t = lastWaiter;        if (t != null && t.waitStatus != Node.CONDITION) {            unlinkCancelledWaiters();            t = lastWaiter;        }        Node node = new Node(Thread.currentThread(), Node.CONDITION);        if (t == null)            firstWaiter = node;        else            t.nextWaiter = node;        lastWaiter = node;        return node;    }        /**     * 清除队列中不是等待状态的线程     */    private void unlinkCancelledWaiters() {        Node t = firstWaiter;        Node trail = null; // 用于保存前一个节点        while (t != null) {            Node next = t.nextWaiter;            if (t.waitStatus != Node.CONDITION) {                t.nextWaiter = null;                if (trail == null)                    firstWaiter = next;                else                    trail.nextWaiter = next;                if (next == null)                    lastWaiter = trail;            }            else                trail = t;            t = next;        }    }}
  1. await() :造成当前线程在接到信号或被中断之前一直处于等待状态。
  2. **await(long time, TimeUnit unit) **:造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
  3. **awaitNanos(long nanosTimeout) **:造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。返回值表示剩余时间,如果在nanosTimesout之前唤醒,那么返回值 = nanosTimeout - 消耗时间,如果返回值 <= 0 ,则可以认定它已经超时了。
  4. **awaitUninterruptibly() **:造成当前线程在接到信号之前一直处于等待状态。【注意:该方法对中断不敏感】。
  5. **awaitUntil(Date deadline) **:造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。如果没有到指定时间就被通知,则返回true,否则表示到了指定时间,返回返回false。
  6. signal():唤醒一个等待线程。该线程从等待方法返回前必须获得与Condition相关的锁。
  7. signal()All:唤醒所有等待线程。能够从等待方法返回的线程必须获得与Condition相关的锁。
等待队列

ConditionObject的等待队列是一个FIFO队列,队列的每个节点都是等待在Condition对象上的线程的引用,在调用Condition的await()方法之后,线程释放锁,构造成相应的节点进入等待队列等待。其中节点的定义复用AQS的Node定义。

等待队列相关操作实现

凤凰彩票app下载安装 3

ConditionObject等待队列相关操作实现

  • ConditionObject包含等待队列的首节点firstWaiter和尾节点lastWaiter;
  • 线程调用await()方法时,调用addConditionWaiter()方法入队:
    • step1:将线程构造成Node;
    • step2:将Node加入到等待队列中。

从队列相关操作的具体实现可以知道等待队列的基本结构如下图所示:

凤凰彩票app下载安装 4

等待队列基本结构

插入节点只需要将原有尾节点的nextWaiter指向当前节点,并且更新尾节点。更新节点并没有像AQS更新同步队列使用CAS是因为调用await()方法的线程必定是获取了锁的线程,锁保证了操作的线程安全。

注:AQS实质上拥有一个同步队列和多个等待队列,具体对应关系如下图所示:

凤凰彩票app下载安装 5

AQS同步队列与等待队列

四、等待await()

    public final void await() throws InterruptedException {        if (Thread.interrupted            throw new InterruptedException();        Node node = addConditionWaiter(); // 当前线程new Node()加入条件队列        int savedState = fullyRelease; // 释放当先线程的锁        int interruptMode = 0;                /**         * 自旋:         * 1.当前节点不在同步队列(刚new的节点肯定不在),挂起当前线程,等待被唤醒         * 2.当其他线程调用同一个ConditionObject的signal方法时,会将队列里的节点放入同步队列,并unpark线程         * 3.如果该节点被唤醒,再自旋检查是否在同步队列。发现已经在队列中,就可以跳出循环,获取lock         */        while (!isOnSyncQueue {            LockSupport.park(this);            if ((interruptMode = checkInterruptWhileWaiting != 0) // 处理打断                break;        }        if (acquireQueued(node, savedState) && interruptMode != THROW_IE) // 获取锁            interruptMode = REINTERRUPT;        if (node.nextWaiter != null) // clean up if cancelled            unlinkCancelledWaiters();        if (interruptMode != 0)            reportInterruptAfterWait(interruptMode);    }

Condition是一种广义上的条件队列。他为线程提供了一种更为灵活的等待/通知模式,线程在调用await方法后执行挂起操作,直到线程等待的某个条件为真时才会被唤醒。Condition必须要配合锁一起使用,因为对共享状态变量的访问发生在多线程环境下。一个Condition的实例必须与一个Lock绑定,因此Condition一般都是作为Lock的内部实现。

等待

调用Condition的await开头的系列方法,当前线程进入等待队列等待,那么Condition的等待实质是await系列方法的具体实现。

await实现

凤凰彩票app下载安装 6

await实现

具体执行流程如下:

  • 调用addConditionWaiter将当前线程加入等待队列;
  • 调用fullRelease释放当前线程节点的同步状态,唤醒后继节点;
  • 线程进入等待状态;
  • 线程被唤醒后,从while循环中退出,调用acquireQueued尝试获取同步状态;
  • 同步状态获取成功后,线程从await方法返回。

其他以await开头的方法具体实现与await基本一致,只是在它的基础上增加了超时限制,不管有没有被唤醒,到达指定时间,等待结束,从await返回。整个await系列方法将线程加入等待队列的流程可以总结为下图:

凤凰彩票app下载安装 7

线程加入等待队列.png

五、唤醒signal()

public final void signal() {        if (!isHeldExclusively // 检查是否拿到锁            throw new IllegalMonitorStateException();        Node first = firstWaiter;        if (first != null)            doSignal;    }        private void doSignal(Node first) {        do {            if ( (firstWaiter = first.nextWaiter) == null)                lastWaiter = null;            first.nextWaiter = null;        } while (!transferForSignal && // 唤醒队列第一个节点                 (first = firstWaiter) != null);    }        final boolean transferForSignal(Node node) {        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))            return false;        Node p = enq; // 加入同步队列        int ws = p.waitStatus;        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))            LockSupport.unpark(node.thread); // 唤醒线程        return true;    }

await():造成当前线程在接到信号或被中断之前一直处于等待状态。

await(long time, TimeUnit unit):造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。

awaitNanos(long nanosTimeout):造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。返回值表示剩余时间,如果在nanosTimesout之前唤醒,那么返回值 = nanosTimeout – 消耗时间,如果返回值 <= 0 ,则可以认定它已经超时了。

awaitUninterruptibly():造成当前线程在接到信号之前一直处于等待状态。【注意:该方法对中断不敏感】。

awaitUntil(Date deadline):造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。如果没有到指定时间就被通知,则返回true,否则表示到了指定时间,返回返回false。

signal():唤醒一个等待线程。该线程从等待方法返回前必须获得与Condition相关的锁。

signal()All:唤醒所有等待线程。能够从等待方法返回的线程必须获得与Condition相关的锁。

Condtion的实现

获取一个Condition必须要通过Lock的newCondition()方法。该方法定义在接口Lock下面,返回的结果是绑定到此 Lock 实例的新 Condition 实例。Condition为一个接口,其下仅有一个实现类ConditionObject,由于Condition的操作需要获取相关的锁,而AQS则是同步锁的实现基础,所以ConditionObject则定义为AQS的内部类。定义如下:

public class ConditionObject implements Condition, java.io.Serializable {
}

唤醒

调用Condition的signal()方法将会唤醒再等待队列中的首节点,该节点也是到目前为止等待时间最长的节点。

signal实现

凤凰彩票app下载安装 8

signal实现

  • step1:前置检查,判断当前线程是否是获取了锁的线程,如果不是抛出异常IllegalMonitorStateException,否则,执行step2;
  • step2:取得等待队列的头结点,头结点不为空执行doSignal,否则,signal结束。

可以看出,doSignal方法是整个signal方法实现的核心,它完成了将线程从唤醒的所有操作。

doSignal实现

凤凰彩票app下载安装 9

doSignal实现

整个doSignal完成了这两个操作:调用transferForSignal将节点从等待队列移动到同步队列,并且,将该节点从等待队列删除。

transferForSignal实现

凤凰彩票app下载安装 10

transferForSignal实现

  • step1:将节点waitStatus设置为0,设置成功执行step2,否则返回false;
  • step2:调用enq方法将该节点加入同步队列;
  • step3:使用LockSuppor.unpark()方法唤醒该节点的线程。

Condition的signalAll()方法,将等待队列中的所有节点全部唤醒,相当于将等待队列中的每一个节点都执行一次signal()。整个signal系列方法将线程从等待队列移动到同步队列可以总结为下图:

凤凰彩票app下载安装 11

线程从等待队列移动到同步队列

参考资料 / 相关推荐

一行一行源码分析清楚 AbstractQueuedSynchronizer

—–J.U.C之Condition

Java多线程系列--“JUC锁”06之 Condition条件

等待队列

每个Condition对象都包含着一个FIFO队列,该队列是Condition对象通知/等待功能的关键。在队列中每一个节点都包含着一个线程引用,该线程就是在该Condition对象上等待的线程。我们看Condition的定义就明白了:

public class ConditionObject implements Condition, java.io.Serializable {
    private static final long serialVersionUID = 1173984872572414699L;

    //头节点
    private transient Node firstWaiter;
    //尾节点
    private transient Node lastWaiter;

    public ConditionObject() {
    }

    /** 省略方法 **/
}

从上面代码可以看出Condition拥有首节点(firstWaiter),尾节点(lastWaiter)。当前线程调用await()方法,将会以当前线程构造成一个节点(Node),并将节点加入到该队列的尾部。结构如下:

凤凰彩票app下载安装 12

Condition

Node里面包含了当前线程的引用。Node定义与AQS的CLH同步队列的节点使用的都是同一个类(AbstractQueuedSynchronized.Node静态内部类)。

Condition的队列结构比CLH同步队列的结构简单些,新增过程较为简单只需要将原尾节点的nextWaiter指向新增节点,然后更新lastWaiter即可。

等待

调用Condition的await()方法会使当前线程进入等待状态,同时会加入到Condition等待队列同时释放锁。当从await()方法返回时,当前线程一定是获取了Condition相关连的锁。

    public final void await() throws InterruptedException {
        // 当前线程中断
        if (Thread.interrupted())
            throw new InterruptedException();
        //当前线程加入等待队列
        Node node = addConditionWaiter();
        //释放锁
        long savedState = fullyRelease(node);
        int interruptMode = 0;
        /**
         * 检测此节点的线程是否在同步队上,如果不在,则说明该线程还不具备竞争锁的资格,则继续等待
         * 直到检测到此节点在同步队列上
         */
        while (!isOnSyncQueue(node)) {
            //线程挂起
            LockSupport.park(this);
            //如果已经中断了,则退出
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
        }
        //竞争同步状态
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        //清理下条件队列中的不是在等待条件的节点
        if (node.nextWaiter != null) // clean up if cancelled
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
    }

此段代码的逻辑是:首先将当前线程新建一个节点同时加入到条件队列中,然后释放当前线程持有的同步状态。然后则是不断检测该节点代表的线程释放出现在CLH同步队列中(收到signal信号之后就会在AQS队列中检测到),如果不存在则一直挂起,否则参与竞争同步状态。

加入条件队列(addConditionWaiter())源码如下:

    private Node addConditionWaiter() {
        Node t = lastWaiter;    //尾节点
        //Node的节点状态如果不为CONDITION,则表示该节点不处于等待状态,需要清除节点
        if (t != null && t.waitStatus != Node.CONDITION) {
            //清除条件队列中所有状态不为Condition的节点
            unlinkCancelledWaiters();
            t = lastWaiter;
        }
        //当前线程新建节点,状态CONDITION
        Node node = new Node(Thread.currentThread(), Node.CONDITION);
        /**
         * 将该节点加入到条件队列中最后一个位置
         */
        if (t == null)
            firstWaiter = node;
        else
            t.nextWaiter = node;
        lastWaiter = node;
        return node;
    }

该方法主要是将当前线程加入到Condition条件队列中。当然在加入到尾节点之前会清楚所有状态不为Condition的节点。

fullyRelease(Node node),负责释放该线程持有的锁。

    final long fullyRelease(Node node) {
        boolean failed = true;
        try {
            //节点状态--其实就是持有锁的数量
            long savedState = getState();
            //释放锁
            if (release(savedState)) {
                failed = false;
                return savedState;
            } else {
                throw new IllegalMonitorStateException();
            }
        } finally {
            if (failed)
                node.waitStatus = Node.CANCELLED;
        }
    }

isOnSyncQueue(Node node):如果一个节点刚开始在条件队列上,现在在同步队列上获取锁则返回true

    final boolean isOnSyncQueue(Node node) {
        //状态为Condition,获取前驱节点为null,返回false
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
        //后继节点不为null,肯定在CLH同步队列中
        if (node.next != null)
            return true;

        return findNodeFromTail(node);
    }

unlinkCancelledWaiters():负责将条件队列中状态不为Condition的节点删除

        private void unlinkCancelledWaiters() {
            Node t = firstWaiter;
            Node trail = null;
            while (t != null) {
                Node next = t.nextWaiter;
                if (t.waitStatus != Node.CONDITION) {
                    t.nextWaiter = null;
                    if (trail == null)
                        firstWaiter = next;
                    else
                        trail.nextWaiter = next;
                    if (next == null)
                        lastWaiter = trail;
                }
                else
                    trail = t;
                t = next;
            }
        }

通知

调用Condition的signal()方法,将会唤醒在等待队列中等待最长时间的节点(条件队列里的首节点),在唤醒节点前,会将节点移到CLH同步队列中。

    public final void signal() {
        //检测当前线程是否为拥有锁的独
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        //头节点,唤醒条件队列中的第一个节点
        Node first = firstWaiter;
        if (first != null)
            doSignal(first);    //唤醒
    }

该方法首先会判断当前线程是否已经获得了锁,这是前置条件。然后唤醒条件队列中的头节点。

doSignal(Node first):唤醒头节点

    private void doSignal(Node first) {
        do {
            //修改头结点,完成旧头结点的移出工作
            if ( (firstWaiter = first.nextWaiter) == null)
                lastWaiter = null;
            first.nextWaiter = null;
        } while (!transferForSignal(first) &&
                (first = firstWaiter) != null);
    }

doSignal(Node first)主要是做两件事:1.修改头节点,2.调用transferForSignal(Node first) 方法将节点移动到CLH同步队列中。transferForSignal(Node first)源码如下:

     final boolean transferForSignal(Node node) {
        //将该节点从状态CONDITION改变为初始状态0,
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;

        //将节点加入到syn队列中去,返回的是syn队列中node节点前面的一个节点
        Node p = enq(node);
        int ws = p.waitStatus;
        //如果结点p的状态为cancel 或者修改waitStatus失败,则直接唤醒
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            LockSupport.unpark(node.thread);
        return true;
    }

整个通知的流程如下:

  1. 判断当前线程是否已经获取了锁,如果没有获取则直接抛出异常,因为获取锁为通知的前置条件。
  2. 如果线程已经获取了锁,则将唤醒条件队列的首节点
  3. 唤醒首节点是先将条件队列中的头节点移出,然后调用AQS的enq(Node node)方法将其安全地移到CLH同步队列中
  4. 最后判断如果该节点的同步状态是否为Cancel,或者修改状态为Signal失败时,则直接调用LockSupport唤醒该节点的线程。

总结

一个线程获取锁后,通过调用Condition的await()方法,会将当前线程先加入到条件队列中,然后释放锁,最后通过isOnSyncQueue(Node node)方法不断自检看节点是否已经在CLH同步队列了,如果是则尝试获取锁,否则一直挂起。当线程调用signal()方法后,程序首先检查当前线程是否获取了锁,然后通过doSignal(Node first)方法唤醒CLH同步队列的首节点。被唤醒的线程,将从await()方法中的while循环中退出来,然后调用acquireQueued()方法竞争同步状态。

Condition的应用

只知道原理,如果不知道使用那就坑爹了,下面是用Condition实现的生产者消费者问题:

public class ConditionTest {
    private LinkedList<String> buffer;    //容器
    private int maxSize ;           //容器最大
    private Lock lock;
    private Condition fullCondition;
    private Condition notFullCondition;

    ConditionTest(int maxSize){
        this.maxSize = maxSize;
        buffer = new LinkedList<String>();
        lock = new ReentrantLock();
        fullCondition = lock.newCondition();
        notFullCondition = lock.newCondition();
    }

    public void set(String string) throws InterruptedException {
        lock.lock();    //获取锁
        try {
            while (maxSize == buffer.size()){
                notFullCondition.await();       //满了,添加的线程进入等待状态
            }

            buffer.add(string);
            fullCondition.signal();
        } finally {
            lock.unlock();      //记得释放锁
        }
    }

    public String get() throws InterruptedException {
        String string;
        lock.lock();
        try {
            while (buffer.size() == 0){
                fullCondition.await();
            }
            string = buffer.poll();
            notFullCondition.signal();
        } finally {
            lock.unlock();
        }
        return string;
    }
}

本文由凤凰平台注册开户发布于编程知识,转载请注明出处:java并发编制程序之Condition凤凰彩票app下载安装:

关键词:

上一篇:没有了
下一篇:貌似处理程序中的session