个人随笔
目录
线程阻塞和唤醒之await()和signal()
2022-12-25 21:04:57

Condition对象的await()方法和signal()方法通常用于线程之间的阻塞和唤醒,但是这两个方法必须在Lock里面,比如ReentrantLock,否则会报错,也不能先执行signal()方法后执行await()方法,这样await()方法执行完后就一直阻塞了,下面是例子。

1、正常使用的代码

  1. public class AwaitAndSignal {
  2. public static void main(String[] args) {
  3. ReentrantLock lock = new ReentrantLock();
  4. Condition condition = lock.newCondition();
  5. new Thread(()->{
  6. lock.lock();
  7. try {
  8. System.out.println(Thread.currentThread().getName()+"进来啦,然后被await阻塞");
  9. condition.await();
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }finally {
  13. lock.unlock();
  14. }
  15. System.out.println(Thread.currentThread().getName()+"被唤醒啦");
  16. },"t1").start();
  17. try {
  18. Thread.sleep(2000);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. new Thread(()->{
  23. lock.lock();
  24. try {
  25. System.out.println(Thread.currentThread().getName()+"signal唤醒了t1");
  26. condition.signal();
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. }finally {
  30. lock.unlock();
  31. }
  32. },"t2").start();
  33. }
  34. }

输出结果

  1. t1进来啦,然后被await阻塞
  2. t2signal唤醒了t1
  3. t1被唤醒啦

跟预想的一致。

2、await()和signal()的使用必须要有锁,没有锁的话会报错

  1. public class AwaitAndSignal {
  2. public static void main(String[] args) {
  3. ReentrantLock lock = new ReentrantLock();
  4. Condition condition = lock.newCondition();
  5. new Thread(()->{
  6. //lock.lock();
  7. try {
  8. System.out.println(Thread.currentThread().getName()+"进来啦,然后被await阻塞");
  9. condition.await();
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }finally {
  13. //lock.unlock();
  14. }
  15. System.out.println(Thread.currentThread().getName()+"被唤醒啦");
  16. },"t1").start();
  17. try {
  18. Thread.sleep(2000);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. new Thread(()->{
  23. //lock.lock();
  24. try {
  25. System.out.println(Thread.currentThread().getName()+"signal唤醒了t1");
  26. condition.signal();
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. }finally {
  30. //lock.unlock();
  31. }
  32. },"t2").start();
  33. }
  34. }
  1. t1进来啦,然后被await阻塞
  2. java.lang.IllegalMonitorStateException
  3. t1被唤醒啦
  4. at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
  5. at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)

3、如果先执行signal()后执行await()则唤醒失败,会阻塞下去

  1. public class AwaitAndSignal {
  2. public static void main(String[] args) {
  3. ReentrantLock lock = new ReentrantLock();
  4. Condition condition = lock.newCondition();
  5. new Thread(()->{
  6. try {
  7. //这里休息三秒,那么就是她唤醒线程先执行才能到这里的阻塞执行了
  8. Thread.sleep(3000);
  9. } catch (InterruptedException e1) {
  10. // TODO Auto-generated catch block
  11. e1.printStackTrace();
  12. }
  13. lock.lock();
  14. try {
  15. System.out.println(Thread.currentThread().getName()+"进来啦,然后被await阻塞");
  16. condition.await();
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }finally {
  20. lock.unlock();
  21. }
  22. System.out.println(Thread.currentThread().getName()+"被唤醒啦");
  23. },"t1").start();
  24. try {
  25. Thread.sleep(2000);
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. }
  29. new Thread(()->{
  30. lock.lock();
  31. try {
  32. System.out.println(Thread.currentThread().getName()+"signal唤醒了t1");
  33. condition.signal();
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. }finally {
  37. lock.unlock();
  38. }
  39. },"t2").start();
  40. }
  41. }
  1. t2signal唤醒了t1
  2. t1进来啦,然后被wait阻塞
 149

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2