Lock接口在之前的章节中多次提及,Condition接口在之前的章节中设计不多,只是下面的文章中略有提及:
Java并发14:并发三特性-可见性定义、可见性问题与可见性保证技术
本章主要通过解读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():唤醒所有线程。