关键词搜索

源码搜索 ×
×

java之wait()、notify()实现非阻塞的生产者和消费者

发布2018-07-03浏览2048次

详情内容

一、对于wait()和notify()的解释

  1. void notify()
  2. Wakes up a single thread that is waiting on this object’s monitor.
  3. 唤醒等待获取锁资源的单个线程
  4. void notifyAll()
  5. Wakes up all threads that are waiting on this object’s monitor.
  6. 唤醒等待获取锁资源的所有线程
  7. void wait( )
  8. Causes the current thread to wait until another thread invokes the notify() method or the notifyAll( ) method for this object.
  9. 释放出对象的锁资源,程序会阻塞在这里

 

 

 

 

 

 

二、使用wait()、notify()、notifyAll()应该要注意的地方

  1、wait( ),notify( ),notifyAll( )都不属于Thread类,属于Object基础类,每个对象都有wait( ),notify( ),notifyAll( ) 的功能,因为每个对象都有锁

   2、当需要调用wait( ),notify( ),notifyAll( )的时候,一定都要在synchronized里面,不然会报 IllegalMonitorStateException 异常,可以这样理解,在synchronized(object) {}里面的代码才能获取到对象的锁。


  3、while循环里而不是if语句下使用wait,这样,会在线程暂停恢复后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知

  4、调用obj.wait( )释放了obj的锁,程序就会阻塞在这里,如果后面被notify()或者notifyAll()方法呼唤醒了之后,那么程序会接着调用obj.wait()后面的程序

    5、notify()唤醒等待获取锁资源的单个线程,notifyAll( )唤醒等待获取锁资源的所有线程

  6、当调用obj.notify/notifyAll后,调用线程依旧持有obj锁,其它线程仍无法获得obj锁,直到调用线程退出synchronized块或者在原有的obj调用wait释放锁,其它的线程才能起来

 

 

 

 

 

三、使用wait()、notify()、notifyAll()实现非阻塞式的消费者和生产者

  1. package wait;
  2. import java.util.PriorityQueue;
  3. public class WaitAndNofityTest {
  4. public static final int COUNT = 5;
  5. //优先队列,消费者在这个队列里面消耗数据,生产者在这个里面生产数据
  6. public PriorityQueue<Integer> queue = new PriorityQueue<Integer>(COUNT);
  7. public static void main(String[] args) {
  8. WaitAndNofityTest waitAndNofityTest = new WaitAndNofityTest();
  9. Cus cus = waitAndNofityTest.new Cus();
  10. Make make = waitAndNofityTest.new Make();
  11. make.start();
  12. cus.start();
  13. }
  14. //消费者线程类
  15. class Cus extends Thread {
  16. @Override
  17. public void run() {
  18. System.out.println("Cus queue size is:" + queue.size());
  19. eatData();
  20. }
  21. public void eatData() {
  22. while (true) {
  23. synchronized (queue) {
  24. System.out.println("go to eatData method size is:" + queue.size());
  25. while (queue.size() == 0) {
  26. try {
  27. System.out.println("Cus start notify");
  28. queue.notify();
  29. System.out.println("Cus start wait");
  30. queue.wait();
  31. System.out.println("Cus wait after");
  32. } catch (InterruptedException e) {
  33. queue.notify();
  34. }
  35. }
  36. queue.poll();
  37. System.out.println("Cus eatData after size is:" + queue.size());
  38. }
  39. }
  40. }
  41. }
  42. //生产者线程类
  43. class Make extends Thread {
  44. @Override
  45. public void run() {
  46. System.out.println("Make queue size is:" + queue.size());
  47. addData();
  48. }
  49. public void addData() {
  50. while (true) {
  51. synchronized (queue) {
  52. System.out.println("go to addData method size is:" + queue.size());
  53. while (queue.size() == COUNT) {
  54. try {
  55. System.out.println("Make start notify");
  56. queue.notify();
  57. System.out.println("Make start wait");
  58. queue.wait();
  59. System.out.println("Make wait after");
  60. } catch (InterruptedException e) {
  61. queue.notify();
  62. }
  63. }
  64. queue.offer(5);
  65. System.out.println("Cus addData after size is:" + queue.size());
  66. }
  67. }
  68. }
  69. }
  70. }

 

 

 

 

四、部分运行结果

  1. Cus addData after size is:5
  2. go to addData method size is:5
  3. Make start notify
  4. Make start wait
  5. Cus wait after
  6. Cus eatData after size is:4
  7. go to eatData method size is:4
  8. Cus eatData after size is:3
  9. go to eatData method size is:3
  10. Cus eatData after size is:2
  11. go to eatData method size is:2
  12. Cus eatData after size is:1
  13. go to eatData method size is:1
  14. Cus eatData after size is:0
  15. go to eatData method size is:0
  16. Cus start notify
  17. Cus start wait
  18. Make wait after
  19. Cus addData after size is:1
  20. go to addData method size is:1
  21. Cus addData after size is:2
  22. go to addData method size is:2
  23. Cus addData after size is:3
  24. go to addData method size is:3
  25. Cus addData after size is:4
  26. go to addData method size is:4
  27. Cus addData after size is:5
  28. go to addData method size is:5
  29. Make start notify
  30. Make start wait
  31. Cus wait after
  32. Cus eatData after size is:4
  33. go to eatData method size is:4
  34. Cus eatData after size is:3
  35. go to eatData method size is:3
  36. Cus eatData after size is:2
  37. go to eatData method size is:2
  38. Cus eatData after size is:1
  39. go to eatData method size is:1
  40. Cus eatData after size is:0
  41. go to eatData method size is:0
  42. Cus start notify
  43. Cus start wait
  44. Make wait after
  45. Cus addData after size is:1
  46. go to addData method size is:1
  47. Cus addData after size is:2
  48. go to addData method size is:2
  49. Cus addData after size is:3
  50. go to addData method size is:3
  51. Cus addData after size is:4
  52. go to addData method size is:4
  53. Cus addData after size is:5
  54. go to addData method size is:5
  55. Make start notify
  56. Make start wait
  57. Cus wait after
  58. Cus eatData after size is:4
  59. go to eatData method size is:4
  60. Cus eatData after size is:3
  61. go to eatData method size is:3
  62. Cus eatData after size is:2
  63. go to eatData method size is:2
  64. Cus eatData after size is:1
  65. go to eatData method siz

如果运行了不理解,你可以自己测试然后分析打印的数据,当然你也可以注释掉2个类里面的任意一个notify方法,然后看是什么效果,是不是和自己分析的结果一样,同样你也可以去掉第一类的wait方法试下,看执行notify方法后是synchronized执行完了呼唤其其它线程或则在调用wait方法之后释放锁后是否也会呼唤其线程?

 

 

 

五、用ArrayBlockingQueue实现阻塞式的生产者和消费者

官方API

  1. package wait;
  2. import java.util.concurrent.ArrayBlockingQueue;
  3. public class BlockTest {
  4. private int COUNT = 5;
  5. private ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(COUNT);
  6. public static void main(String[] args) {
  7. BlockTest test = new BlockTest();
  8. Make make = test.new Make();
  9. Cus cus = test.new Cus();
  10. make.start();
  11. cus.start();
  12. }
  13. class Cus extends Thread {
  14. @Override
  15. public void run() {
  16. eatData();
  17. }
  18. private void eatData() {
  19. while (true) {
  20. try {
  21. queue.take();
  22. System.out.println("队列取一个元素,队列剩余"+queue.size() + "元素");
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. }
  28. }
  29. class Make extends Thread {
  30. @Override
  31. public void run() {
  32. addData();
  33. }
  34. private void addData() {
  35. while(true){
  36. try {
  37. queue.put(5);
  38. System.out.println("队列插入一个元素,队列剩余空间:" + (COUNT-queue.size()));
  39. } catch (InterruptedException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43. }
  44. }
  45. }

 

 

 

 

 

 

 

 

 

 

六、部分运行结果

  1. 队列取一个元素,队列剩余4元素
  2. 队列取一个元素,队列剩余3元素
  3. 队列取一个元素,队列剩余2元素
  4. 队列取一个元素,队列剩余1元素
  5. 队列取一个元素,队列剩余0元素
  6. 队列插入一个元素,队列剩余空间:4
  7. 队列插入一个元素,队列剩余空间:3
  8. 队列插入一个元素,队列剩余空间:2
  9. 队列插入一个元素,队列剩余空间:1
  10. 队列插入一个元素,队列剩余空间:0
  11. 队列取一个元素,队列剩余4元素
  12. 队列取一个元素,队列剩余3元素
  13. 队列取一个元素,队列剩余2元素
  14. 队列取一个元素,队列剩余1元素
  15. 队列取一个元素,队列剩余0元素
  16. 队列插入一个元素,队列剩余空间:4
  17. 队列插入一个元素,队列剩余空间:3
  18. 队列插入一个元素,队列剩余空间:2
  19. 队列插入一个元素,队列剩余空间:1
  20. 队列插入一个元素,队列剩余空间:0
  21. 队列取一个元素,队列剩余4元素
  22. 队列取一个元素,队列剩余3元素
  23. 队列取一个元素,队列剩余2元素
  24. 队列取一个元素,队列剩余1元素
  25. 队列取一个元素,队列剩余0元素
  26. 队列插入一个元素,队列剩余空间:4
  27. 队列插入一个元素,队列剩余空间:3
  28. 队列插入一个元素,队列剩余空间:2
  29. 队列插入一个元素,队列剩余空间:1
  30. 队列插入一个元素,队列剩余空间:0
  31. 队列取一个元素,队列剩余4元素
  32. 队列取一个元素,队列剩余3元素
  33. 队列取一个元素,队列剩余2元素
  34. 队列取一个元素,队列剩余1元素
  35. 队列取一个元素,队列剩余0元素
  36. 队列插入一个元素,队列剩余空间:4
  37. 队列插入一个元素,队列剩余空间:3
  38. 队列插入一个元素,队列剩余空间:2
  39. 队列插入一个元素,队列剩余空间:1
  40. 队列插入一个元素,队列剩余空间:0
  41. 队列取一个元素,队列剩余4元素
  42. 队列取一个元素,队列剩余3元素
  43. 队列取一个元素,队列剩余2元素
  44. 队列取一个元素,队列剩余1元素
  45. 队列取一个元素,队列剩余0元素
  46. 队列插入一个元素,队列剩余空间:4
  47. 队列插入一个元素,队列剩余空间:3
  48. 队列插入一个元素,队列剩余空间:2
  49. 队列插入一个元素,队列剩余空间:1
  50. 队列插入一个元素,队列剩余空间:0
  51. 队列取一个元素,队列剩余4元素
  52. 队列取一个元素,队列剩余3元素
  53. 队列取一个元素,队列剩余2元素
  54. 队列取一个元素,队列剩余1元素
  55. 队列取一个元素,队列剩余0元素
  56. 队列插入一个元素,队列剩余空间:4
  57. 队列插入一个元素,队列剩余空间:3
  58. 队列插入一个元素,队列剩余空间:2
  59. 队列插入一个元素,队列剩余空间:1
  60. 队列插入一个元素,队列剩余空间:0
  61. 队列取一个元素,队列剩余4元素
  62. 队列取一个元素,队列剩余3元素
  63. 队列取一个元素,队列剩余2元素
  64. 队列取一个元素,队列剩余1元素
  65. 队列取一个元素,队列剩余0元素
  66. 队列插入一个元素,队列剩余空间:4
  67. 队列插入一个元素,队列剩余空间:3
  68. 队列插入一个元素,队列剩余空间:2
  69. 队列插入一个元素,队列剩余空间:1
  70. 队列插入一个元素,队列剩余空间:0
  71. 队列取一个元素,队列剩余4元素

 

 

 

 

 

 

 

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载