问题描述
在使用Condition进行线程的挂起和唤醒的时候,我经常见到以下的使用方法
Thread1调用Await()方法等待Thread2的Signal唤醒,为了避免长时间的等待,又加了超时的限制,所以Thread1通常写成Condition.await(long,TimeUnit)。但是事实真的是在超时之后,Condition就会返回吗?
问题出现的环境背景及自己尝试过哪些方法
我翻看了一下相关的源码,发现并不是这个样子的。可以通过以下的代码来检测
相关代码
// 请把代码文本粘贴到下方(请勿用图片代替代码)
public class TestConditionAwait {
private static ReentrantLock lock = new ReentrantLock();
private static Logger Log = LoggerFactory.getLogger(TestConditionAwait.class);
public static void main(String[] args) throws InterruptedException {
final Condition condition = lock.newCondition();
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
Thread.currentThread().setName("ConditionAwait-Thread-");
Log.error(Thread.currentThread().getName() + " beforeAwaitTime:" + System.currentTimeMillis());
condition.await(5000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Log.error(Thread.currentThread().getName() + " finishAwaitTime:" + System.currentTimeMillis());
}finally {
lock.unlock();
Log.error(Thread.currentThread().getName() + " unlockTime:" + System.currentTimeMillis());
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread().setName("ConditionSignal-Thread-");
try{
Log.error(Thread.currentThread().getName() + " getLockTime:" + System.currentTimeMillis());
thread1.interrupt();
lock.lock();
long currentTime = System.currentTimeMillis();
while (System.currentTimeMillis() - currentTime < 8000){
}
condition.signal();
Log.error(Thread.currentThread().getName() + " signalTime:" + System.currentTimeMillis());
}catch (Exception e){
}finally {
lock.unlock();
Log.error(Thread.currentThread().getName() + " unlockTime:" + System.currentTimeMillis());
}
}
});
thread1.start();
Thread.sleep(50);
thread2.start();
}
}
你代码的结果是这样来的,thread1在await后放弃了锁,thread2获得锁并开始循环,5000ms后,thread1从条件变量等待队列里面被唤醒,此时thread1要重新获得锁才能继续执行下去,但是锁被thread2占用,所以不得不等到thread2释放锁之后,也就是8000ms之后才能继续执行。
thread1从条件变量等待队列中被超时唤醒后又进入了锁等待队列。