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唤醒了t1t1被唤醒啦
跟预想的一致。
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.IllegalMonitorStateExceptiont1被唤醒啦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 blocke1.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唤醒了t1t1进来啦,然后被wait阻塞
