Condition对象的await()方法和signal()方法通常用于线程之间的阻塞和唤醒,但是这两个方法必须在Lock里面,比如ReentrantLock,否则会报错,也不能先执行signal()方法后执行await()方法,这样await()方法执行完后就一直阻塞了,下面是例子。
1、正常使用的代码
public class AwaitAndSignal {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
new Thread(()->{
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"进来啦,然后被await阻塞");
condition.await();
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
System.out.println(Thread.currentThread().getName()+"被唤醒啦");
},"t1").start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"signal唤醒了t1");
condition.signal();
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
},"t2").start();
}
}
输出结果
t1进来啦,然后被await阻塞
t2signal唤醒了t1
t1被唤醒啦
跟预想的一致。
2、await()和signal()的使用必须要有锁,没有锁的话会报错
public class AwaitAndSignal {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
new Thread(()->{
//lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"进来啦,然后被await阻塞");
condition.await();
} catch (Exception e) {
e.printStackTrace();
}finally {
//lock.unlock();
}
System.out.println(Thread.currentThread().getName()+"被唤醒啦");
},"t1").start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
//lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"signal唤醒了t1");
condition.signal();
} catch (Exception e) {
e.printStackTrace();
}finally {
//lock.unlock();
}
},"t2").start();
}
}
t1进来啦,然后被await阻塞
java.lang.IllegalMonitorStateException
t1被唤醒啦
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
3、如果先执行signal()后执行await()则唤醒失败,会阻塞下去
public class AwaitAndSignal {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
new Thread(()->{
try {
//这里休息三秒,那么就是她唤醒线程先执行才能到这里的阻塞执行了
Thread.sleep(3000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"进来啦,然后被await阻塞");
condition.await();
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
System.out.println(Thread.currentThread().getName()+"被唤醒啦");
},"t1").start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"signal唤醒了t1");
condition.signal();
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
},"t2").start();
}
}
t2signal唤醒了t1
t1进来啦,然后被wait阻塞