Java并发20:Lock系列-Condition接口基本方法学习实例
本章主要通过解读Condition接口的源码注释,来学习Condition接口的各个方法。
1.Condition接口与Lock接口
在Java并发18章节,我们对Lock接口与synchronized关键字的区别于联系进行了学习。
其实在功能上,我们可以将Lock接口作为synchronized关键字的升级版。
在Java并发07章节,而我们已知,obj.wati()/obj.notify()/obj.notifyAll常用来与synchronized关键字合作,进行线程状态控制。
同样的,Condition接口也提供了一系列比obj.wati()/obj.notify()/obj.notifyAll更加灵活和丰富的方法和Lock接口合作,进行线程状态控制。
2.JDK源码注释
public interface Condition { /** * Causes the current thread to wait until it is signalled or * {@linkplain Thread#interrupt interrupted}. * * <p>The lock associated with this {@code Condition} is atomically * released and the current thread becomes disabled for thread scheduling * purposes and lies dormant until <em>one</em> of four things happens: * <ul> * <li>Some other thread invokes the {@link #signal} method for this * {@code Condition} and the current thread happens to be chosen as the * thread to be awakened; or * <li>Some other thread invokes the {@link #signalAll} method for this * {@code Condition}; or * <li>Some other thread {@linkplain Thread#interrupt interrupts} the * current thread, and interruption of thread suspension is supported; or * <li>A "<em>spurious wakeup</em>" occurs. * </ul> * * <p>In all cases, before this method can return the current thread must * re-acquire the lock associated with this condition. When the * thread returns it is <em>guaranteed</em> to hold this lock. * * <p>If the current thread: * <ul> * <li>has its interrupted status set on entry to this method; or * <li>is {@linkplain Thread#interrupt interrupted} while waiting * and interruption of thread suspension is supported, * </ul> * then {@link InterruptedException} is thrown and the current thread's * interrupted status is cleared. It is not specified, in the first * case, whether or not the test for interruption occurs before the lock * is released. * ... */ void await() throws InterruptedException; /** * Causes the current thread to wait until it is signalled. * * <p>The lock associated with this condition is atomically * released and the current thread becomes disabled for thread scheduling * purposes and lies dormant until <em>one</em> of three things happens: * <ul> * <li>Some other thread invokes the {@link #signal} method for this * {@code Condition} and the current thread happens to be chosen as the * thread to be awakened; or * <li>Some other thread invokes the {@link #signalAll} method for this * {@code Condition}; or * <li>A "<em>spurious wakeup</em>" occurs. * </ul> * * <p>In all cases, before this method can return the current thread must * re-acquire the lock associated with this condition. When the * thread returns it is <em>guaranteed</em> to hold this lock. * * <p>If the current thread's interrupted status is set when it enters * this method, or it is {@linkplain Thread#interrupt interrupted} * while waiting, it will continue to wait until signalled. When it finally * returns from this method its interrupted status will still * be set. * ... */ void awaitUninterruptibly(); /** * Causes the current thread to wait until it is signalled or interrupted, * or the specified waiting time elapses. * * <p>The lock associated with this condition is atomically * released and the current thread becomes disabled for thread scheduling * purposes and lies dormant until <em>one</em> of five things happens: * <ul> * <li>Some other thread invokes the {@link #signal} method for this * {@code Condition} and the current thread happens to be chosen as the * thread to be awakened; or * <li>Some other thread invokes the {@link #signalAll} method for this * {@code Condition}; or * <li>Some other thread {@linkplain Thread#interrupt interrupts} the * current thread, and interruption of thread suspension is supported; or * <li>The specified waiting time elapses; or * <li>A "<em>spurious wakeup</em>" occurs. * </ul> * * <p>In all cases, before this method can return the current thread must * re-acquire the lock associated with this condition. When the * thread returns it is <em>guaranteed</em> to hold this lock. * * <p>If the current thread: * <ul> * <li>has its interrupted status set on entry to this method; or * <li>is {@linkplain Thread#interrupt interrupted} while waiting * and interruption of thread suspension is supported, * </ul> * then {@link InterruptedException} is thrown and the current thread's * interrupted status is cleared. It is not specified, in the first * case, whether or not the test for interruption occurs before the lock * is released. * * <p>The method returns an estimate of the number of nanoseconds * remaining to wait given the supplied {@code nanosTimeout} * value upon return, or a value less than or equal to zero if it * timed out. This value can be used to determine whether and how * long to re-wait in cases where the wait returns but an awaited * condition still does not hold. Typical uses of this method take * the following form: * * <pre> {@code * boolean aMethod(long timeout, TimeUnit unit) { * long nanos = unit.toNanos(timeout); * lock.lock(); * try { * while (!conditionBeingWaitedFor()) { * if (nanos <= 0L) * return false; * nanos = theCondition.awaitNanos(nanos); * } * // ... * } finally { * lock.unlock(); * } * }}</pre> * * <p>Design note: This method requires a nanosecond argument so * as to avoid truncation errors in reporting remaining times. * Such precision loss would make it difficult for programmers to * ensure that total waiting times are not systematically shorter * than specified when re-waits occur. * ... */ long awaitNanos(long nanosTimeout) throws InterruptedException; /** * Causes the current thread to wait until it is signalled or interrupted, * or the specified waiting time elapses. This method is behaviorally * equivalent to: * <pre> {@code awaitNanos(unit.toNanos(time)) > 0}</pre> * * @param time the maximum time to wait * @param unit the time unit of the {@code time} argument * @return {@code false} if the waiting time detectably elapsed * before return from the method, else {@code true} * @throws InterruptedException if the current thread is interrupted * (and interruption of thread suspension is supported) */ boolean await(long time, TimeUnit unit) throws InterruptedException; /** * Causes the current thread to wait until it is signalled or interrupted, * or the specified deadline elapses. * * <p>The lock associated with this condition is atomically * released and the current thread becomes disabled for thread scheduling * purposes and lies dormant until <em>one</em> of five things happens: * <ul> * <li>Some other thread invokes the {@link #signal} method for this * {@code Condition} and the current thread happens to be chosen as the * thread to be awakened; or * <li>Some other thread invokes the {@link #signalAll} method for this * {@code Condition}; or * <li>Some other thread {@linkplain Thread#interrupt interrupts} the * current thread, and interruption of thread suspension is supported; or * <li>The specified deadline elapses; or * <li>A "<em>spurious wakeup</em>" occurs. * </ul> * * <p>In all cases, before this method can return the current thread must * re-acquire the lock associated with this condition. When the * thread returns it is <em>guaranteed</em> to hold this lock. * * * <p>If the current thread: * <ul> * <li>has its interrupted status set on entry to this method; or * <li>is {@linkplain Thread#interrupt interrupted} while waiting * and interruption of thread suspension is supported, * </ul> * then {@link InterruptedException} is thrown and the current thread's * interrupted status is cleared. It is not specified, in the first * case, whether or not the test for interruption occurs before the lock * is released. * * * <p>The return value indicates whether the deadline has elapsed, * which can be used as follows: * <pre> {@code * boolean aMethod(Date deadline) { * boolean stillWaiting = true; * lock.lock(); * try { * while (!conditionBeingWaitedFor()) { * if (!stillWaiting) * return false; * stillWaiting = theCondition.awaitUntil(deadline); * } * // ... * } finally { * lock.unlock(); * } * }}</pre> * * ... */ boolean awaitUntil(Date deadline) throws InterruptedException; /** * Wakes up one waiting thread. * * <p>If any threads are waiting on this condition then one * is selected for waking up. That thread must then re-acquire the * lock before returning from {@code await}. * ... */ void signal(); /** * Wakes up all waiting threads. * * <p>If any threads are waiting on this condition then they are * all woken up. Each thread must re-acquire the lock before it can * return from {@code await}. * ... */ void signalAll(); }
3.源码解读
通过解读上面的源码,将Condition接口提供的方法总结如下:
1.void await() throws InterruptedException;
- 让当前线程进入等待状态,直到它被唤醒或被中断。
- 与当前Condition对象相关联的Lock锁会自动释放。
- 为了线程调度目的,当前线程会变为不可用的,直到出现以下四种情形之一:
- 其他线程调用了当前Condition对象的signal()方法,并且当前线程恰好被选为被唤醒线程。
- 其他线程调用了当前Condition对象的signalAll()方法
- 其他线程调用了当前线程的interrupt()方法,而当前线程支持线程中断。
- 产生虚假唤醒。
- 以上所有的情形中,在awit()方法返回之前,当前线程必须重新获取与当前Condition对象相关联的Lock锁。
- 在执行awit()方法过程中,如果当前线程被中断(interrupt())了,则会抛出一个InterruptedException异常,并将中断状态重置。
2.void awaitUninterruptibly();
- 让当前线程进入等待状态,直到它被唤醒。
- 与当前Condition对象相关联的Lock锁会自动释放。
- 为了线程调度目的,当前线程会变为不可用的,直到出现以下三种情形之一:
- 其他线程调用了当前Condition对象的signal()方法,并且当前线程恰好被选为被唤醒线程。
- 其他线程调用了当前Condition对象的signalAll()方法
- 产生虚假唤醒。
- 以上所有的情形中,在awit()方法返回之前,当前线程必须重新获取与当前Condition对象相关联的Lock锁。
- 该等待不可中断。
3.long awaitNanos(long nanosTimeout) throws InterruptedException;
- 让当前线程进入等待状态,直到它被唤醒、被中断或限定时间超时。
- 与当前Condition对象相关联的Lock锁会自动释放。
- 为了线程调度目的,当前线程会变为不可用的,直到出现以下五种情形之一:
- 其他线程调用了当前Condition对象的signal()方法,并且当前线程恰好被选为被唤醒线程。
- 其他线程调用了当前Condition对象的signalAll()方法
- 其他线程调用了当前线程的interrupt()方法,而当前线程支持线程中断。
- 限定的等待时间超时。
- 产生虚假唤醒。
- 以上所有的情形中,在awit()方法返回之前,当前线程必须重新获取与当前Condition对象相关联的Lock锁。
- 在执行awit()方法过程中,如果当前线程被中断(interrupt())了,则会抛出一个InterruptedException异常,并将中断状态重置。
- 这个方法会返回剩余的等待时间;如果已经超时,则返回值可能是0或负值。这个值可以用来确定是否还要继续等待。使用纳秒是为了进行精度控制。通常这个方法的用法如下:
boolean aMethod(long timeout, TimeUnit unit) { //获取纳秒 long nanos = unit.toNanos(timeout); //加锁 lock.lock(); try { //如果继续等待 while (!conditionBeingWaitedFor()) { //如果已经超时,则... if (nanos <= 0L) return false; //获取剩余等待时间 nanos = theCondition.awaitNanos(nanos); } // ... } finally { //解锁 lock.unlock(); } }
4.boolean await(long time, TimeUnit unit) throws InterruptedException;
- 让当前线程进入等待状态,直到它被唤醒、被中断或限定时间超时。
- 这个方法等同于awaitNanos(unit.toNanos(time)) > 0,不再赘述。
5.boolean awaitUntil(Date deadline) throws InterruptedException;
- 让当前线程进入等待状态,直到它被唤醒、被中断或截止时间过去。
- 与当前Condition对象相关联的Lock锁会自动释放。
- 为了线程调度目的,当前线程会变为不可用的,直到出现以下五种情形之一:
- 其他线程调用了当前Condition对象的signal()方法,并且当前线程恰好被选为被唤醒线程。
- 其他线程调用了当前Condition对象的signalAll()方法
- 其他线程调用了当前线程的interrupt()方法,而当前线程支持线程中断。
- 指定的截止时间已经过去。
- 产生虚假唤醒。
- 以上所有的情形中,在awit()方法返回之前,当前线程必须重新获取与当前Condition对象相关联的Lock锁。
- 在执行awit()方法过程中,如果当前线程被中断(interrupt())了,则会抛出一个InterruptedException异常,并将中断状态重置。
- 这个方法的返回值表示截止时间是否已经过去。
通常这个方法的用法如下:
boolean aMethod(Date deadline) { boolean stillWaiting = true; //加锁 lock.lock(); try { //如果继续等待 while (!conditionBeingWaitedFor()) { if (!stillWaiting) return false; //获取指定的截止时间已经过去 stillWaiting = theCondition.awaitUntil(deadline); } // ... } finally { //解锁 lock.unlock(); } }
6.void signal();
- 唤醒一个线程。
- 如果当前的Condition对象上有等待的线程,则唤醒其中的一个线程。
- 这个被唤醒的线程必须在从awit()方法返回之前重新获取锁。
7.void signalAll();
- 唤醒所有线程。
- 如果当前的Condition对象上有等待的线程,则唤醒全部的线程。
- 每个被唤醒的线程必须在从awit()方法返回之前重新获取锁。
4.实例代码
实例场景:
- 定义5个等待线程如下:
- 线程0:通过await()进行等待。
- 线程1:通过awaitNanos(long)进行等待,long=1000000000,即1秒钟。
- 线程2:通过await(long,TimeUnit)进行等待,long=2,TimeUnit=TimeUnit.SECONDS,即2秒钟。
- 线程3:通过awaitUntil(deadline)进行等待,System.currentTimeMillis() + 5000,即5秒之后的时刻。
- 线程4:通过awaitUninterruptibly()进行等待。
- 定义3种测试场景:
- 等待所有线程自己结束。
- 在5个测试线程启动100毫秒之后,通过interrupt()中断所有线程。
- 在5个测试线程启动100毫秒之后,通过condition.signalAll()唤醒所有线程。
结果预测:
- 场景一:等待所有线程自己结束。
- 线程0:通过await()等待,此方法只能被中断和被唤醒,所以此线程不会终止。
- 线程1:通过awaitNanos(long)等待1秒钟,此方法可被中断、被唤醒或者超时,所以线程会在1秒之后自动终止。
- 线程2:通过await(long,TimeUnit)等待2秒钟,此方法可被中断、被唤醒或者超时,所以线程会在2秒之后自动终止。
- 线程3:通过awaitUntil(deadline)等待至5秒之后,此方法可被中断、被唤醒或者到期,所以线程会在5秒之后自动终止。
- 线程4:通过awaitUninterruptibly()等待,此方法只能被唤醒,所以此线程不会终止。
- 在5个测试线程启动100毫秒之后,通过interrupt()中断所有线程。
- 线程0:通过await()等待,此方法可被中断和被唤醒,所以此线程会因为被中断而终止。
- 线程1:通过awaitNanos(long)等待1秒钟,此方法可被中断、被唤醒或者超时,所以此线程会因为被中断而终止。
- 线程2:通过await(long,TimeUnit)等待2秒钟,此方法可被中断、被唤醒或者超时,所以此线程会因为被中断而终止。
- 线程3:通过awaitUntil(deadline)等待至5秒之后,此方法可被中断、被唤醒或者到期,所以此线程会因为被中断而终止。
- 线程4:通过awaitUninterruptibly()等待,此方法只能被唤醒,所以此线程不会终止。
- 在5个测试线程启动100毫秒之后,通过condition.signalAll()唤醒所有线程。
- 线程0:通过await()等待,此方法可被中断和被唤醒,所以此线程会因为被唤醒而终止。
- 线程1:通过awaitNanos(long)等待1秒钟,此方法可被中断、被唤醒或者超时,所以此线程会因为被唤醒而终止。
- 线程2:通过await(long,TimeUnit)等待2秒钟,此方法可被中断、被唤醒或者超时,所以此线程会因为被唤醒而终止。
- 线程3:通过awaitUntil(deadline)等待至5秒之后,此方法可被中断、被唤醒或者到期,所以此线程会因为被唤醒而终止。
- 线程4:通过awaitUninterruptibly()等待,此方法只能被唤醒,所以此线程会因为被唤醒而终止。
实例代码:
/** * <p>Lock接口-Condition学习-可中断锁、可定时锁</p> * * @author hanchao 2018/3/18 14:45 **/ public class ConditionDemo { //定义一个非公平的锁 private static Lock lock = new ReentrantLock(false); /** * <p>Lock接口-Condition学习</p> * * @author hanchao 2018/3/18 14:46 **/ public static void main(String[] args) throws InterruptedException { Condition condition = lock.newCondition(); //线程0:通过await()进行等待,直到被中断或者被唤醒 Thread thread0 = new Thread(() -> { System.out.println("线程[await()-" + Thread.currentThread().getName() + "]尝试获取锁..."); lock.lock(); System.out.println("线程[await()-" + Thread.currentThread().getName() + "]获取了锁."); try { //通过await()进行等待,直到被中断或者被唤醒 condition.await(); System.out.println("线程[await()-" + Thread.currentThread().getName() + "]被唤醒..."); } catch (InterruptedException e) { //e.printStackTrace(); System.out.println("线程[await()-" + Thread.currentThread().getName() + "]被中断..."); } finally { lock.unlock(); System.out.println("线程[await()-" + Thread.currentThread().getName() + "]释放了锁."); } }); //线程1:通过awaitNanos(long)进行等待,直到被中断、被唤醒、或时间超时 Thread thread1 = new Thread(() -> { System.out.println("线程[awaitNanos(long)-" + Thread.currentThread().getName() + "]尝试获取锁..."); lock.lock(); System.out.println("线程[awaitNanos(long)-" + Thread.currentThread().getName() + "]获取了锁."); try { //通过awaitNanos(long)进行等待,直到被中断、被唤醒或时间用尽 //剩余等待时间 Long remainTime = condition.awaitNanos(1000000000);//等待1秒钟 if (remainTime > 0) {//如果剩余时间大于0,则表明此线程是被唤醒的 System.out.println("线程[awaitNanos(long)-" + Thread.currentThread().getName() + "]被唤醒..."); } else {//如果剩余时间小于等于0,则表明此线程是因为等待时间耗尽而停止等待的 System.out.println("线程[awaitNanos(long)-" + Thread.currentThread().getName() + "]等待时间用尽,停止等待..."); } } catch (InterruptedException e) { //e.printStackTrace(); System.out.println("线程[awaitNanos(long)-" + Thread.currentThread().getName() + "]被中断..."); } finally { //尝试解锁 lock.unlock(); System.out.println("线程[awaitNanos(long)-" + Thread.currentThread().getName() + "]释放了锁."); } }); //线程2:通过await(long,TimeUnit)进行等待,直到被中断、被唤醒、或时间超时 Thread thread2 = new Thread(() -> { System.out.println("线程[await(long,TimeUnit)-" + Thread.currentThread().getName() + "]尝试获取锁..."); lock.lock(); System.out.println("线程[await(long,TimeUnit)-" + Thread.currentThread().getName() + "]获取了锁."); try { //通过awaitNanos(long)进行等待,直到被中断、被唤醒或时间用尽 //返回true则表明是被唤醒的,false表明是时间用尽 boolean result = condition.await(2, TimeUnit.SECONDS);//等待2秒钟 if (result) { System.out.println("线程[await(long,TimeUnit)-" + Thread.currentThread().getName() + "]被唤醒..."); } else { System.out.println("线程[await(long,TimeUnit)-" + Thread.currentThread().getName() + "]等待时间用尽,停止等待..."); } } catch (InterruptedException e) { //e.printStackTrace(); System.out.println("线程[await(long,TimeUnit)-" + Thread.currentThread().getName() + "]被中断..."); } finally { //尝试解锁 lock.unlock(); System.out.println("线程[await(long,TimeUnit)-" + Thread.currentThread().getName() + "]释放了锁."); } }); //线程3:通过awaitUntil(deadline)进行等待,直到被中断、被唤醒、或时间到期 Thread thread3 = new Thread(() -> { System.out.println("线程[awaitUntil(deadline)-" + Thread.currentThread().getName() + "]尝试获取锁..."); lock.lock(); System.out.println("线程[awaitUntil(deadline)-" + Thread.currentThread().getName() + "]获取了锁."); try { Date deadline = new Date(System.currentTimeMillis() + 5000);//5秒之后 //通过awaitUntil(deadline)进行等待,直到被中断、被唤醒或到达截止时间 //返回true则表明是被唤醒的,false表明是时间用尽 boolean result = condition.awaitUntil(deadline); if (result) { System.out.println("线程[awaitUntil(deadline)-" + Thread.currentThread().getName() + "]被唤醒..."); } else { System.out.println("线程[awaitUntil(deadline)-" + Thread.currentThread().getName() + "]到达截止时间,停止等待..."); } } catch (InterruptedException e) { //e.printStackTrace(); System.out.println("线程[awaitUntil(deadline)-" + Thread.currentThread().getName() + "]被中断..."); } finally { //尝试解锁 lock.unlock(); System.out.println("线程[awaitUntil(deadline)-" + Thread.currentThread().getName() + "]释放了锁."); } }); //线程4:通过awaitUninterruptibly()进行等待,直到被唤醒 Thread thread4 = new Thread(() -> { System.out.println("线程[awaitUninterruptibly()-" + Thread.currentThread().getName() + "]尝试获取锁..."); lock.lock(); System.out.println("线程[awaitUninterruptibly()-" + Thread.currentThread().getName() + "]获取了锁."); try { //通过awaitUninterruptibly()进行等待,直到被唤醒 condition.awaitUninterruptibly(); System.out.println("线程[awaitUninterruptibly()-" + Thread.currentThread().getName() + "]被唤醒..."); } finally { //尝试解锁 lock.unlock(); System.out.println("线程[awaitUninterruptibly()-" + Thread.currentThread().getName() + "]释放了锁."); } }); //启动所有线程 thread0.start(); thread1.start(); thread2.start(); thread3.start(); thread4.start(); /** * 0 等待线程自己结束 * 1 通过中断结束线程 * 2 通过condition.signalAll()唤醒所有线程 */ int type = 2; switch (type) { case 0: //让能自己结束的自己结束 Thread.sleep(100); System.out.println("======================等待线程自己结束"); break; case 1: //尝试中断线程 Thread.sleep(100); System.out.println("======================尝试中断线程"); thread0.interrupt(); thread1.interrupt(); thread2.interrupt(); thread3.interrupt(); thread4.interrupt(); break; case 2: Thread.sleep(100); System.out.println("======================开始唤醒所有还在等待的线程"); //在main线程中,通过condition.signalAll()唤醒所有 System.out.println("线程[condition.signalAll()-" + Thread.currentThread().getName() + "]尝试获取锁..."); lock.lock(); System.out.println("线程[condition.signalAll()-" + Thread.currentThread().getName() + "]获取了锁,并唤醒所有等待的线程..."); try { //通过awaitUninterruptibly()进行等待,直到被唤醒 condition.signalAll(); } finally { //尝试解锁 lock.unlock(); System.out.println("线程[condition.signalAll()-" + Thread.currentThread().getName() + "]释放了锁."); } break; default: break; } } }
运行结果:
- 等待所有线程自己结束。
线程[awaitNanos(long)-Thread-1]尝试获取锁... 线程[awaitNanos(long)-Thread-1]获取了锁. 线程[awaitUntil(deadline)-Thread-3]尝试获取锁... 线程[awaitUntil(deadline)-Thread-3]获取了锁. 线程[await(long,TimeUnit)-Thread-2]尝试获取锁... 线程[awaitUninterruptibly()-Thread-4]尝试获取锁... 线程[await()-Thread-0]尝试获取锁... 线程[await(long,TimeUnit)-Thread-2]获取了锁. 线程[awaitUninterruptibly()-Thread-4]获取了锁. 线程[await()-Thread-0]获取了锁. ======================等待线程自己结束 线程[awaitNanos(long)-Thread-1]等待时间用尽,停止等待... 线程[awaitNanos(long)-Thread-1]释放了锁. 线程[await(long,TimeUnit)-Thread-2]等待时间用尽,停止等待... 线程[await(long,TimeUnit)-Thread-2]释放了锁. 线程[awaitUntil(deadline)-Thread-3]到达截止时间,停止等待... 线程[awaitUntil(deadline)-Thread-3]释放了锁.
在5个测试线程启动100毫秒之后,通过interrupt()中断所有线程。
线程[await()-Thread-0]尝试获取锁... 线程[await(long,TimeUnit)-Thread-2]尝试获取锁... 线程[awaitNanos(long)-Thread-1]尝试获取锁... 线程[awaitUntil(deadline)-Thread-3]尝试获取锁... 线程[awaitUninterruptibly()-Thread-4]尝试获取锁... 线程[await()-Thread-0]获取了锁. 线程[await(long,TimeUnit)-Thread-2]获取了锁. 线程[awaitNanos(long)-Thread-1]获取了锁. 线程[awaitUntil(deadline)-Thread-3]获取了锁. 线程[awaitUninterruptibly()-Thread-4]获取了锁. ======================尝试中断线程 线程[awaitNanos(long)-Thread-1]被中断... 线程[awaitNanos(long)-Thread-1]释放了锁. 线程[await()-Thread-0]被中断... 线程[await()-Thread-0]释放了锁. 线程[await(long,TimeUnit)-Thread-2]被中断... 线程[await(long,TimeUnit)-Thread-2]释放了锁. 线程[awaitUntil(deadline)-Thread-3]被中断... 线程[awaitUntil(deadline)-Thread-3]释放了锁.
在5个测试线程启动100毫秒之后,通过condition.signalAll()唤醒所有线程。
线程[awaitNanos(long)-Thread-1]尝试获取锁... 线程[await()-Thread-0]尝试获取锁... 线程[await(long,TimeUnit)-Thread-2]尝试获取锁... 线程[awaitUntil(deadline)-Thread-3]尝试获取锁... 线程[awaitNanos(long)-Thread-1]获取了锁. 线程[awaitUninterruptibly()-Thread-4]尝试获取锁... 线程[awaitUninterruptibly()-Thread-4]获取了锁. 线程[await()-Thread-0]获取了锁. 线程[await(long,TimeUnit)-Thread-2]获取了锁. 线程[awaitUntil(deadline)-Thread-3]获取了锁. ======================开始唤醒所有还在等待的线程 线程[condition.signalAll()-main]尝试获取锁... 线程[condition.signalAll()-main]获取了锁,并唤醒所有等待的线程... 线程[condition.signalAll()-main]释放了锁. 线程[awaitNanos(long)-Thread-1]被唤醒... 线程[awaitNanos(long)-Thread-1]释放了锁. 线程[awaitUninterruptibly()-Thread-4]被唤醒... 线程[awaitUninterruptibly()-Thread-4]释放了锁. 线程[await()-Thread-0]被唤醒... 线程[await()-Thread-0]释放了锁. 线程[await(long,TimeUnit)-Thread-2]被唤醒... 线程[await(long,TimeUnit)-Thread-2]释放了锁. 线程[awaitUntil(deadline)-Thread-3]被唤醒... 线程[awaitUntil(deadline)-Thread-3]释放了锁.
测试结果与预测一致。
5.总结
下面对上述的7个方法进行一句话总结:
- await():等待,直到被唤醒或被中断。
- awaitUninterruptibly():等待,直到被唤醒,中断无效。
- awaitNanos(long nanosTimeout):限定的纳秒时间内等待,直到被唤醒、被中断或限定时间超时。
- await(long time, TimeUnit unit):限定的时间内等待,直到被唤醒、被中断或限定时间超时。
- awaitUntil(Date deadline):指定的截止时间等待,直到被唤醒、被中断或截止时间过去。
- signal():唤醒一个线程。
- signalAll():唤醒所有线程。