每天一例多线程[day9]-----多线程间的通信

volatile实现

 
  1. package com.jeff.base.conn008;

  2.  
  3. import java.util.ArrayList;

  4. import java.util.List;

  5. /**

  6. * 定义t1和t2两个线程:

  7. * t1线程往list中加入元素

  8. * t2线程发现list元素个数为5时抛出异常,停止t2线程

  9. *

  10. * @author jeff

  11. * @param args

  12. */

  13. public class ListAdd1 {

  14.  
  15. private volatile static List list = new ArrayList();

  16.  
  17. public void add(){

  18. list.add("bjsxt");

  19. }

  20. public int size(){

  21. return list.size();

  22. }

  23.  
  24. public static void main(String[] args) {

  25.  
  26. final ListAdd1 list1 = new ListAdd1();

  27.  
  28. Thread t1 = new Thread(new Runnable() {

  29. @Override

  30. public void run() {

  31. try {

  32. for(int i = 0; i <10; i++){

  33. list1.add();

  34. System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");

  35. Thread.sleep(500);

  36. }

  37. } catch (InterruptedException e) {

  38. e.printStackTrace();

  39. }

  40. }

  41. }, "t1");

  42.  
  43. Thread t2 = new Thread(new Runnable() {

  44. @Override

  45. public void run() {

  46. while(true){

  47. if(list1.size() == 5){

  48. System.out.println("当前线程收到通知:"

  49. + Thread.currentThread().getName() + " list size = 5 线程停止..");

  50. throw new RuntimeException();

  51. }

  52. }

  53. }

  54. }, "t2");

  55.  
  56. t1.start();

  57. t2.start();

  58. }

  59.  
  60.  
  61. }

打印结果:

 
  1. 当前线程:t1添加了一个元素..

  2. 当前线程:t1添加了一个元素..

  3. 当前线程:t1添加了一个元素..

  4. 当前线程:t1添加了一个元素..

  5. 当前线程:t1添加了一个元素..

  6. 当前线程收到通知:t2 list size = 5 线程停止..

  7. Exception in thread "t2" java.lang.RuntimeException

  8. at com.jeff.base.conn008.ListAdd1$2.run(ListAdd1.java:50)

  9. at java.lang.Thread.run(Thread.java:722)

  10. 当前线程:t1添加了一个元素..

  11. 当前线程:t1添加了一个元素..

  12. 当前线程:t1添加了一个元素..

  13. 当前线程:t1添加了一个元素..

  14. 当前线程:t1添加了一个元素..

 

wait和notify实现

 
  1. package com.jeff.base.conn008;

  2.  
  3. import java.util.ArrayList;

  4. import java.util.List;

  5. import java.util.Queue;

  6. import java.util.concurrent.CountDownLatch;

  7. import java.util.concurrent.LinkedBlockingDeque;

  8. import java.util.concurrent.LinkedBlockingQueue;

  9. /**

  10. * wait notfiy 方法,wait释放锁,notfiy不释放锁

  11. * @author jeff

  12. *

  13. */

  14. public class ListAdd2 {

  15. private volatile static List list = new ArrayList();

  16.  
  17. public void add(){

  18. list.add("bjsxt");

  19. }

  20. public int size(){

  21. return list.size();

  22. }

  23.  
  24. public static void main(String[] args) {

  25.  
  26. final ListAdd2 list2 = new ListAdd2();

  27.  
  28. // 1 实例化出来一个 lock

  29. // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用

  30. final Object lock = new Object();

  31.  
  32.  
  33. // final CountDownLatch countDownLatch = new CountDownLatch(1);

  34.  
  35. Thread t1 = new Thread(new Runnable() {

  36. @Override

  37. public void run() {

  38. try {

  39. synchronized (lock) {

  40. for(int i = 0; i <10; i++){

  41. list2.add();

  42. System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");

  43. Thread.sleep(500);

  44. if(list2.size() == 5){

  45. System.out.println("已经发出通知..");

  46. // countDownLatch.countDown();

  47. lock.notify();

  48. }

  49. }

  50. }

  51. } catch (InterruptedException e) {

  52. e.printStackTrace();

  53. }

  54.  
  55. }

  56. }, "t1");

  57.  
  58. Thread t2 = new Thread(new Runnable() {

  59. @Override

  60. public void run() {

  61. synchronized (lock) {

  62. if(list2.size() != 5){

  63. try {

  64. System.out.println("t2进入...");

  65. lock.wait();

  66. // countDownLatch.await();

  67. } catch (InterruptedException e) {

  68. e.printStackTrace();

  69. }

  70. }

  71. System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");

  72. throw new RuntimeException();

  73. }

  74. }

  75. }, "t2");

  76.  
  77. t2.start();

  78. t1.start();

  79.  
  80. }

  81.  
  82. }

打印结果:

 
  1. t2进入...

  2. 当前线程:t1添加了一个元素..

  3. 当前线程:t1添加了一个元素..

  4. 当前线程:t1添加了一个元素..

  5. 当前线程:t1添加了一个元素..

  6. 当前线程:t1添加了一个元素..

  7. 已经发出通知..

  8. 当前线程:t1添加了一个元素..

  9. 当前线程:t1添加了一个元素..

  10. 当前线程:t1添加了一个元素..

  11. 当前线程:t1添加了一个元素..

  12. 当前线程:t1添加了一个元素..

  13. 当前线程:t2收到通知线程停止..

  14. Exception in thread "t2" java.lang.RuntimeException

  15. at com.jeff.base.conn008.ListAdd2$2.run(ListAdd2.java:72)

  16. at java.lang.Thread.run(Thread.java:722)

我们发现以后结果并不是实时的,分析下执行过程:

     t2线程先执行,执行到await方法时释放锁,然后t1获得锁,当t1添加5个元素后,调用notify方法唤醒t2线程,但是notify方法并不释放锁,所以t2线程此时并不能得到锁,直到t1线程添加完10个元素以后释放锁,t2线程await才不再阻塞,打印“收到通知线程停止”。

 

CountDownLatch方式

 
  1. package com.jeff.base.conn008;

  2.  
  3. import java.util.ArrayList;

  4. import java.util.List;

  5. import java.util.Queue;

  6. import java.util.concurrent.CountDownLatch;

  7. import java.util.concurrent.LinkedBlockingDeque;

  8. import java.util.concurrent.LinkedBlockingQueue;

  9. /**

  10. * wait notfiy 方法,wait释放锁,notfiy不释放锁

  11. * @author jeff

  12. *

  13. */

  14. public class ListAdd2 {

  15. private volatile static List list = new ArrayList();

  16.  
  17. public void add(){

  18. list.add("bjsxt");

  19. }

  20. public int size(){

  21. return list.size();

  22. }

  23.  
  24. public static void main(String[] args) {

  25.  
  26. final ListAdd2 list2 = new ListAdd2();

  27.  
  28. // 1 实例化出来一个 lock

  29. // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用

  30. // final Object lock = new Object();

  31.  
  32.  
  33. final CountDownLatch countDownLatch = new CountDownLatch(1);

  34.  
  35. Thread t1 = new Thread(new Runnable() {

  36. @Override

  37. public void run() {

  38. try {

  39. // synchronized (lock) {

  40. for(int i = 0; i <10; i++){

  41. list2.add();

  42. System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");

  43. Thread.sleep(500);

  44. if(list2.size() == 5){

  45. System.out.println("已经发出通知..");

  46. countDownLatch.countDown();

  47. // lock.notify();

  48. }

  49. }

  50. // }

  51. } catch (InterruptedException e) {

  52. e.printStackTrace();

  53. }

  54.  
  55. }

  56. }, "t1");

  57.  
  58. Thread t2 = new Thread(new Runnable() {

  59. @Override

  60. public void run() {

  61. // synchronized (lock) {

  62. if(list2.size() != 5){

  63. try {

  64. System.out.println("t2进入...");

  65. // lock.wait();

  66. countDownLatch.await();

  67. } catch (InterruptedException e) {

  68. e.printStackTrace();

  69. }

  70. }

  71. System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");

  72. throw new RuntimeException();

  73. // }

  74. }

  75. }, "t2");

  76.  
  77. t2.start();

  78. t1.start();

  79.  
  80. }

  81.  
  82. }

打印结果:

 
  1. t2进入...

  2. 当前线程:t1添加了一个元素..

  3. 当前线程:t1添加了一个元素..

  4. 当前线程:t1添加了一个元素..

  5. 当前线程:t1添加了一个元素..

  6. 当前线程:t1添加了一个元素..

  7. 已经发出通知..

  8. Exception in thread "t2" java.lang.RuntimeException

  9. at com.jeff.base.conn008.ListAdd2$2.run(ListAdd2.java:72)

  10. at java.lang.Thread.run(Thread.java:722)

  11. 当前线程:t1添加了一个元素..

  12. 当前线程:t2收到通知线程停止..

  13. 当前线程:t1添加了一个元素..

  14. 当前线程:t1添加了一个元素..

  15. 当前线程:t1添加了一个元素..

  16. 当前线程:t1添加了一个元素..

执行countDown方法后,计数器减去1,变为0,t2线程停止阻塞实时开始执行...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值