lesson5:Condition的原理分析及demo展示

Condition 将 Object 监视器方法(wait,notify,和notifyAll)分解成截然不同的对象,以便通过将这些对象与任意Lock实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。每个condition都是与一个锁关联的,一个锁可以创造一个或多个condition。

关于condition的描述,参考资料:http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/java/util/concurrent/locks/Condition.html

demo源码:https://github.com/mantuliu/javaAdvance 中的Lesson5相关的类

我们来看一下Condition接口的实现类ConditionObject

    public class ConditionObject implements Condition, java.io.Serializable {
        private static final long serialVersionUID = 1173984872572414699L;
        /** First node of condition queue. */
        private transient Node firstWaiter;//第一个等待节点,后面我们会看到每个wait的线程都是一个等待节点
        /** Last node of condition queue. */
        private transient Node lastWaiter;//最后一个等待节点

        /**
         * Creates a new <tt>ConditionObject</tt> instance.
         */
        public ConditionObject() { }

        // Internal methods
        /**         * Implements interruptible condition wait.         * <ol>         * <li> If current thread is interrupted, throw InterruptedException.         * <li> Save lock state returned by {@link #getState}.         * <li> Invoke {@link #release} with         *      saved state as argument, throwing         *      IllegalMonitorStateException if it fails.         * <li> Block until signalled or interrupted.         * <li> Reacquire by invoking specialized version of         *      {@link #acquire} with saved state as argument.         * <li> If interrupted while blocked in step 4, throw InterruptedException.         * </ol>         */        public final void await() throws InterruptedException {            if (Thread.interrupted())//判断线程是否被中断了,如果是则抛出中断异常                throw new InterruptedException();            Node node = addConditionWaiter();//创建一个新的等待节点,此节点是等待队列的最后一个节点,先进先出            int savedState = fullyRelease(node);//释放线程占用的锁            int interruptMode = 0;            while (!isOnSyncQueue(node)) {//判断node是否被唤醒                LockSupport.park(this);//等待unpark许可                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);        }
        /**
         * Adds a new waiter to wait queue.
         * @return its new wait node
         */
        private Node addConditionWaiter() {//在wait队列中创建一个新的节点
            Node t = lastWaiter;
            // If lastWaiter is cancelled, clean out.
            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;
        }

        /**
         * Removes and transfers nodes until hit non-cancelled one or
         * null. Split out from signal in part to encourage compilers
         * to inline the case of no waiters.
         * @param first (non-null) the first node on condition queue
         */
        private void doSignal(Node first) {
            do {
                if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                first.nextWaiter = null;
            } while (!transferForSignal(first) &&
                     (first = firstWaiter) != null);
        }

        /**
         * Removes and transfers all nodes.
         * @param first (non-null) the first node on condition queue
         */
        private void doSignalAll(Node first) {
            lastWaiter = firstWaiter = null;
            do {
                Node next = first.nextWaiter;
                first.nextWaiter = null;
                transferForSignal(first);
                first = next;
            } while (first != null);
        }

        /**
         * Unlinks cancelled waiter nodes from condition queue.
         * Called only while holding lock. This is called when
         * cancellation occurred during condition wait, and upon
         * insertion of a new waiter when lastWaiter is seen to have
         * been cancelled. This method is needed to avoid garbage
         * retention in the absence of signals. So even though it may
         * require a full traversal, it comes into play only when
         * timeouts or cancellations occur in the absence of
         * signals. It traverses all nodes rather than stopping at a
         * particular target to unlink all pointers to garbage nodes
         * without requiring many re-traversals during cancellation
         * storms.
         */
        private void unlinkCancelledWaiters() {//释放wait队列中所有非等待状态的节点
            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;
            }
        }

        // public methods

        /**
         * Moves the longest-waiting thread, if one exists, from the
         * wait queue for this condition to the wait queue for the
         * owning lock.
         *
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *         returns {@code false}
         */
        public final void signal() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                doSignal(first);//通知第一个节点,它调用的方法调用了LockSupport.unpark(node.thread);unpark与await中的park对应
        }

        /**
         * Moves all threads from the wait queue for this condition to
         * the wait queue for the owning lock.
         *
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *         returns {@code false}
         */
        public final void signalAll() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                doSignalAll(first);//通知所有节点
        }

        /**
         * Implements uninterruptible condition wait.
         * <ol>
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with
         *      saved state as argument, throwing
         *      IllegalMonitorStateException if it fails.
         * <li> Block until signalled.
         * <li> Reacquire by invoking specialized version of
         *      {@link #acquire} with saved state as argument.
         * </ol>
         */
        public final void awaitUninterruptibly() {
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            boolean interrupted = false;
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                if (Thread.interrupted())
                    interrupted = true;
            }
            if (acquireQueued(node, savedState) || interrupted)
                selfInterrupt();
        }

        /*
         * For interruptible waits, we need to track whether to throw
         * InterruptedException, if interrupted while blocked on
         * condition, versus reinterrupt current thread, if
         * interrupted while blocked waiting to re-acquire.
         */

        /** Mode meaning to reinterrupt on exit from wait */
        private static final int REINTERRUPT =  1;
        /** Mode meaning to throw InterruptedException on exit from wait */
        private static final int THROW_IE    = -1;

        /**
         * Checks for interrupt, returning THROW_IE if interrupted
         * before signalled, REINTERRUPT if after signalled, or
         * 0 if not interrupted.
         */
        private int checkInterruptWhileWaiting(Node node) {
            return Thread.interrupted() ?
                (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
                0;
        }

        /**
         * Throws InterruptedException, reinterrupts current thread, or
         * does nothing, depending on mode.
         */
        private void reportInterruptAfterWait(int interruptMode)
            throws InterruptedException {
            if (interruptMode == THROW_IE)
                throw new InterruptedException();
            else if (interruptMode == REINTERRUPT)
                selfInterrupt();
        }/**
         * Implements timed condition wait.
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with
         *      saved state as argument, throwing
         *      IllegalMonitorStateException if it fails.
         * <li> Block until signalled, interrupted, or timed out.
         * <li> Reacquire by invoking specialized version of
         *      {@link #acquire} with saved state as argument.
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * </ol>
         */
        public final long awaitNanos(long nanosTimeout)
                throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            long lastTime = System.nanoTime();
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                if (nanosTimeout <= 0L) {
                    transferAfterCancelledWait(node);
                    break;
                }
                LockSupport.parkNanos(this, nanosTimeout);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;

                long now = System.nanoTime();
                nanosTimeout -= now - lastTime;
                lastTime = now;
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return nanosTimeout - (System.nanoTime() - lastTime);
        }

        /**
         * Implements absolute timed condition wait.
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with
         *      saved state as argument, throwing
         *      IllegalMonitorStateException if it fails.
         * <li> Block until signalled, interrupted, or timed out.
         * <li> Reacquire by invoking specialized version of
         *      {@link #acquire} with saved state as argument.
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * <li> If timed out while blocked in step 4, return false, else true.
         * </ol>
         */
        public final boolean awaitUntil(Date deadline)
                throws InterruptedException {
            if (deadline == null)
                throw new NullPointerException();
            long abstime = deadline.getTime();
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            boolean timedout = false;
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                if (System.currentTimeMillis() > abstime) {
                    timedout = transferAfterCancelledWait(node);
                    break;
                }
                LockSupport.parkUntil(this, abstime);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return !timedout;
        }

        /**
         * Implements timed condition wait.
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with
         *      saved state as argument, throwing
         *      IllegalMonitorStateException if it fails.
         * <li> Block until signalled, interrupted, or timed out.
         * <li> Reacquire by invoking specialized version of
         *      {@link #acquire} with saved state as argument.
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * <li> If timed out while blocked in step 4, return false, else true.
         * </ol>
         */
        public final boolean await(long time, TimeUnit unit)
                throws InterruptedException {
            if (unit == null)
                throw new NullPointerException();
            long nanosTimeout = unit.toNanos(time);
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            long lastTime = System.nanoTime();
            boolean timedout = false;
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                if (nanosTimeout <= 0L) {
                    timedout = transferAfterCancelledWait(node);
                    break;
                }
                if (nanosTimeout >= spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
                long now = System.nanoTime();
                nanosTimeout -= now - lastTime;
                lastTime = now;
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return !timedout;
        }

        //  support for instrumentation

        /**
         * Returns true if this condition was created by the given
         * synchronization object.
         *
         * @return {@code true} if owned
         */
        final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
            return sync == AbstractQueuedSynchronizer.this;
        }

        /**
         * Queries whether any threads are waiting on this condition.
         * Implements {@link AbstractQueuedSynchronizer#hasWaiters}.
         *
         * @return {@code true} if there are any waiting threads
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *         returns {@code false}
         */
        protected final boolean hasWaiters() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    return true;
            }
            return false;
        }

        /**
         * Returns an estimate of the number of threads waiting on
         * this condition.
         * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength}.
         *
         * @return the estimated number of waiting threads
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *         returns {@code false}
         */
        protected final int getWaitQueueLength() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            int n = 0;
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    ++n;
            }
            return n;
        }

        /**
         * Returns a collection containing those threads that may be
         * waiting on this Condition.
         * Implements {@link AbstractQueuedSynchronizer#getWaitingThreads}.
         *
         * @return the collection of threads
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *         returns {@code false}
         */
        protected final Collection<Thread> getWaitingThreads() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            ArrayList<Thread> list = new ArrayList<Thread>();
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION) {
                    Thread t = w.thread;
                    if (t != null)
                        list.add(t);
                }
            }
            return list;
        }
    }

在分析了ConditionObject的代码后,我产生了以下几点推论:

1.await()方法是可以响应线程中断命令的;

2.await()和signal()方法在当前线程锁定了Condition对应的锁时才能使用;

3.一个锁对应多个Condition对象,每个Condition的signal()方法只通知相同Condition的await()方法,condition之间不会互相通知;

4.signal()被调用时,wait队列中的第一个对象会被唤醒,signalAll()时,wait队列中元素的全部按先入先出的顺序被唤醒;

5.如果既存在await的线程,又存在一直等待lock()的线程,当signal()的线程完成时,lock()的线程优先级比await()的线程优先级高,当所有lock()线程获取到锁并释放后,才会轮到await()线程。

下面我将用代码来证明这几个推论:

下面的例子展示了await()方法是响应中断的,而awaitUninterruptibly()是无视外部中断的:

package com.mantu.advance;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * blog http://www.cnblogs.com/mantu/
 * github https://github.com/mantuliu/
 * @author mantu
 *
 */
public class Lesson5ConditionAwaitInterrupt implements Runnable {
    public static ReentrantLock lock = new ReentrantLock();
    public static Condition con = lock.newCondition();
    public static void main(String [] args) throws InterruptedException{
        Thread thread = new Thread(new Lesson5ConditionAwaitInterrupt());
        thread.start();
        Thread.sleep(5000L);//当前线程睡5秒
        System.out.println("开始中断线程");
        thread.interrupt();//中断线程
    }

    @Override
    public void run() {
        try{
            lock.lock();
            while(true){
                System.out.println("开始等待signal的通知");
                con.await();
                //con.awaitUninterruptibly();
            }
        }
        catch(Exception ex){
            ex.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }
}

下面的例子展示了当前线程一定是在获得了condition对应的锁的情况下,才能调用await和signal等方法:

package com.mantu.advance;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * blog http://www.cnblogs.com/mantu/
 * github https://github.com/mantuliu/
 * @author mantu
 *
 */
public class Lesson5ConditionAwaitWithLock implements Runnable {
    public static ReentrantLock lock = new ReentrantLock();
    public static Condition con = lock.newCondition();

    public static void main(String [] args) throws InterruptedException {
        Thread thread = new Thread(new Lesson5ConditionAwaitWithLock());
        thread.start();
        try {
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        con.signal();//抛出异常
        con.await();

    }
    @Override
    public void run() {
        try {
            lock.lock();
            con.signal();
            System.out.println("通知信号发送完毕");
            con.await();
            System.out.println("接收到通知信号");
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }

}

下面的例子展示了一个锁对应多个Condition对象,每个Condition的signal()方法只通知相同Condition的await()方法,condition之间不会互相通知;signal()被调用时,wait队列中的第一个对象会被唤醒:

package com.mantu.advance;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * blog http://www.cnblogs.com/mantu/
 * github https://github.com/mantuliu/
 * @author mantu
 *
 */
public class Lesson5ConditonsRelation{
    public static ReentrantLock lock = new ReentrantLock();
    public static Condition conOne = lock.newCondition();
    public static Condition conTwo = lock.newCondition();
    public static void main(String [] args){
        for(int i=0;i<3;i++){
            new Thread(new UsedConditionOne()).start();
            new Thread(new UsedConditionTwo()).start();
        }
        try {
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            lock.lock();
            Lesson5ConditonsRelation.conOne.signal();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }

        try {
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            lock.lock();
            Lesson5ConditonsRelation.conTwo.signal();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }
}
class UsedConditionOne implements Runnable{

    @Override
    public void run() {
        Lock lock = Lesson5ConditonsRelation.lock;
        try {
            lock.lock();
            System.out.println("UsedConditionOne ‘s thread "+ Thread.currentThread().getId() + " 开始等待");
            Lesson5ConditonsRelation.conOne.await();
            System.out.println("UsedConditionOne ‘s thread "+ Thread.currentThread().getId() + " 等待完毕");
            Lesson5ConditonsRelation.conOne.signal();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }

}
class UsedConditionTwo implements Runnable{

    @Override
    public void run() {
        Lock lock = Lesson5ConditonsRelation.lock;
        try {
            lock.lock();
            System.out.println("UsedConditionTwo ‘s thread "+ Thread.currentThread().getId() + " 开始等待");
            Lesson5ConditonsRelation.conTwo.await();
            System.out.println("UsedConditionTwo ‘s thread "+ Thread.currentThread().getId() + " 等待完毕");
            Lesson5ConditonsRelation.conTwo.signal();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }

}

下面的demo展示了signalAll()方法会通知所有的await()线程:

package com.mantu.advance;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * blog http://www.cnblogs.com/mantu/
 * github https://github.com/mantuliu/
 * @author mantu
 *
 */
public class Lesson5ConditionSignalAll implements Runnable{

    public static ReentrantLock lock = new ReentrantLock();
    public static Condition con = lock.newCondition();
    public static void main(String [] args){
        for(int i=0;i<30;i++){
            Thread thread = new Thread(new Lesson5ConditionSignalAll());
            thread.start();
        }
        try {
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            lock.lock();
            con.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }
    @Override
    public void run() {
        try {
            lock.lock();
            System.out.println("thread "+ Thread.currentThread().getId() + " 开始等待");
            con.await();
            System.out.println("thread "+ Thread.currentThread().getId() + " 等待完毕");
            Thread.sleep(1000L);
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }
}

下面的demo展示了在同等条件下去获取锁,lock()线程的优先级会比await()线程的优先级高:

package com.mantu.advance;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * blog http://www.cnblogs.com/mantu/
 * github https://github.com/mantuliu/
 * @author mantu
 *
 */
public class Lesson5ConditionSignalAwaitLock {
    public static ReentrantLock lock = new ReentrantLock();
    public static Condition conOne = lock.newCondition();
    public static void main(String [] args) throws InterruptedException{
        for(int i=0;i<3;i++){
            new Thread(new ThreadAwait()).start();
        }
        Thread.currentThread().sleep(1000L);
        new Thread(new ThreadSignal()).start();
        Thread.currentThread().sleep(1000L);
        for(int i=0;i<3;i++){
            new Thread(new ThreadLock()).start();
        }
    }
}

class ThreadAwait implements Runnable{

    @Override
    public void run() {
        Lock lock = Lesson5ConditionSignalAwaitLock.lock;
        try {
            lock.lock();
            System.out.println("ThreadAwait ‘s thread "+ Thread.currentThread().getId() + " 开始等待");
            Lesson5ConditionSignalAwaitLock.conOne.await();
            System.out.println("ThreadAwait ‘s thread "+ Thread.currentThread().getId() + " 等待完毕");
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }

}

class ThreadSignal implements Runnable{

    @Override
    public void run() {
        Lock lock = Lesson5ConditionSignalAwaitLock.lock;
        try {
            lock.lock();
            System.out.println("ThreadSignal ‘s thread "+ Thread.currentThread().getId() + " 拿到了锁");
            Thread.currentThread().sleep(2000L);
            new Thread(new ThreadLock()).start();
            System.out.println("ThreadSignal ‘s thread "+ Thread.currentThread().getId() + " 开始通知");
            Lesson5ConditionSignalAwaitLock.conOne.signal();
            Lesson5ConditionSignalAwaitLock.conOne.signal();
            Lesson5ConditionSignalAwaitLock.conOne.signal();
            System.out.println("ThreadSignal ‘s thread "+ Thread.currentThread().getId() + " 通知完毕");
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }

}

class ThreadLock implements Runnable{

    @Override
    public void run() {
        Lock lock = Lesson5ConditionSignalAwaitLock.lock;
        try {
            System.out.println("ThreadLock ‘s thread "+ Thread.currentThread().getId() + " 进入线程开始拿锁");
            lock.lock();
            System.out.println("ThreadLock ‘s thread "+ Thread.currentThread().getId() + " 拿到了锁");
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }

}

到此为止,本文已经分析完毕:最后再强调一下重点:

1.await()方法是可以响应线程中断命令的;

2.await()和signal()方法在当前线程锁定了Condition对应的锁时才能使用;

3.一个锁对应多个Condition对象,每个Condition的signal()方法只通知相同Condition的await()方法,condition之间不会互相通知;

4.signal()被调用时,wait队列中的第一个对象会被唤醒,signalAll()时,wait队列中元素的全部按先入先出的顺序被唤醒;

5.如果既存在await的线程,又存在一直等待lock()的线程,当signal()的线程完成时,lock()的线程优先级比await()的线程优先级高,当所有lock()线程获取到锁并释放后,才会轮到await()线程。

时间: 2024-10-19 17:17:18

lesson5:Condition的原理分析及demo展示的相关文章

4*4矩阵键盘原理分析以及代码展示

简单介绍下矩阵键盘的原理: 矩阵键盘4个输入端口ROW[3:0] 接收由FPGA产生的键盘扫描输入信号,而4个输出COL[3:0] 将按键操作的信息变化输入到FPGA扫描分析电路,进而得到按键的操作码. 输入端口分别接了4个上拉电阻,当4个输入端口输入若都为1时,则有无论按哪个按键,输出都为1,所以 若刚开始的时候对四个输入端口赋0,则只要按下任何一个按键,键盘上的4个输出则肯定有1变为0,而且能够判断到是哪一列,但是并不知道是哪一行,所以此时就要用到键盘扫描,何为键盘扫描,就是只要让输入端口的

Android大图片裁剪终极解决方案 原理分析

约几个月前,我正为公司的APP在Android手机上实现拍照截图而烦恼不已. 上网搜索,确实有不少的例子,大多都是抄来抄去,而且水平多半处于demo的样子,可以用来讲解知识点,但是一碰到实际项目,就漏洞百出. 当时我用大众化的解决方案,暂时性的做了一个拍照截图的功能,似乎看起来很不错.问题随之而来,我用的是小米手机,在别的手机上都运行正常,小米这里却总是碰钉子.虽然我是个理性的米粉,但是也暗地里把小米的工程师问候了个遍.真是惭愧! 翻文档也找不出个答案来,我一直对com.android.came

AQS底层原理分析

J.U.C 简介 Java.util.concurrent 是在并发编程中比较常用的工具类,里面包含很多用来在并发场景中使用的组件.比如线程池.阻塞队列.计时器.同步器.并发集合等等.并发包的作者是大名鼎鼎的 Doug Lea.我们在接下来剖析一些经典的比较常用的组件的设计思想. Lock Lock 在 J.U.C 中是最核心的组件,前面我们讲 synchronized 的时候说过,锁最重要的特性就是解决并发安全问题.为什么要以 Lock 作为切入点呢?如果有看过 J.U.C 包中的所有组件,一

AbstractQueuedSynchronizer的介绍和原理分析(转)

简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过继承同步器并需要实现它的方法来管理其状态,管理的方式就是通过类似acquire和release的方式来操纵状态.然而多线程环境中对状态的操纵必须确保原子性,因此子类对于状态的把握,需要使用这个同步器提供的以下三个方法对状态进行操作: java.util.concurrent.locks.Abstra

Android 4.4 KitKat NotificationManagerService使用详解与原理分析(一)__使用详解

概况 Android在4.3的版本中(即API 18)加入了NotificationListenerService,根据SDK的描述(AndroidDeveloper)可以知道,当系统收到新的通知或者通知被删除时,会触发NotificationListenerService的回调方法.同时在Android 4.4 中新增了Notification.extras 字段,也就是说可以使用NotificationListenerService获取系统通知具体信息,这在以前是需要用反射来实现的. 转载请

browserify运行原理分析

目前对于前端工程师而言,如果只针对浏览器编写代码,那么很简单,只需要在页面的script脚本中引入所用js就可以了. 但是某些情况下,我们可能需要在服务端也跑一套类似的逻辑代码,考虑如下这些情景(以node作为后端为例): 1.spa的应用,需要同时支持服务端直出页面以及客户端pjax拉取数据渲染,客户端和服务器公用一套渲染模板并执行大部分类似的逻辑. 2.一个通过websocket对战的游戏,客户端和服务端可能需要进行类似的逻辑计算,两套代码分别用于对用户客户端的展示以及服务端实际数值的计算.

RemoteViews原理分析及应用

转载请注明出处:http://blog.csdn.net/ahence/article/details/62418926 RemoteViews基本概念 RemoteViews乍一看名字似乎也是一种View,实则不然,它并不是View.来看RemoteViews的定义及官方说明: /** * A class that describes a view hierarchy that can be displayed in * another process. The hierarchy is in

WebViewJavascriptBridge 原理分析

WebViewJavascriptBridge 原理分析 网上好多都是在介绍 WebViewJavascriptBridge如何使用,这篇文章就来说说 WebViewJavascriptBridge 设计原理. 主要从两个过程来讲一下:js调用UIViewController中的代码(Native),Native调用js 1.概述 首先有两个问题: a.Native(中的UIWebView)是否可以直接调用js method(方法)? 可以. b.js 是否可以直接调用Native的mthod?

Tomcat7.0源码分析——请求原理分析(上)

前言 谈起Tomcat的诞生,最早可以追溯到1995年.近20年来,Tomcat始终是使用最广泛的Web服务器,由于其使用Java语言开发,所以广为Java程序员所熟悉.很多人早期的J2EE项目,由程序员自己实现Jsp页面或者Servlet接受请求,后来借助Struts1.Struts2.Spring等中间件后,实际也是利用Filter或者Servlet处理请求,大家肯定要问了,这些Servlet处理的请求来自哪里?Tomcat作为Web服务器是怎样将HTTP请求交给Servlet的呢? 本文就