一、使用while方式来实现线程之间的通信

  1. package com.ietree.multithread.sync;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. public class MyList {
  7.  
  8. private volatile static List list = new ArrayList();
  9.  
  10. public void add() {
  11. list.add("apple");
  12. }
  13.  
  14. public int size() {
  15. return list.size();
  16. }
  17.  
  18. public static void main(String[] args) {
  19.  
  20. final MyList list1 = new MyList();
  21.  
  22. Thread t1 = new Thread(new Runnable() {
  23. @Override
  24. public void run() {
  25. try {
  26. for (int i = 0; i < 10; i++) {
  27. list1.add();
  28. System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
  29. Thread.sleep(500);
  30. }
  31. } catch (InterruptedException e) {
  32. e.printStackTrace();
  33. }
  34. }
  35. }, "t1");
  36.  
  37. Thread t2 = new Thread(new Runnable() {
  38. @Override
  39. public void run() {
  40. while (true) {
  41. if (list1.size() == 5) {
  42. System.out.println("当前线程收到通知:" + Thread.currentThread().getName() + " list size = 5 线程停止..");
  43. throw new RuntimeException();
  44. }
  45. }
  46. }
  47. }, "t2");
  48.  
  49. t1.start();
  50. t2.start();
  51. }
  52. }

程序输出:

  1. 当前线程:t1添加了一个元素..
  2. 当前线程:t1添加了一个元素..
  3. 当前线程:t1添加了一个元素..
  4. 当前线程:t1添加了一个元素..
  5. 当前线程:t1添加了一个元素..
  6. Exception in thread "t2" 当前线程收到通知:t2 list size = 5 线程停止..
  7. java.lang.RuntimeException
  8. at com.ietree.multithread.sync.MyList$2.run(MyList.java:43)
  9. at java.lang.Thread.run(Unknown Source)
  10. 当前线程:t1添加了一个元素..
  11. 当前线程:t1添加了一个元素..
  12. 当前线程:t1添加了一个元素..
  13. 当前线程:t1添加了一个元素..
  14. 当前线程:t1添加了一个元素..

理解:线程Thread2不停地通过while语句检测这个条件(list.size()==5)是否成立 ,从而实现了线程间的通信。但是这种方式会浪费CPU资源。

二、wait notfiy 方法实现多线程中线程之间的通信

使用这种方式实现线程通信需要注意:wait和notify必须配合synchronized关键字使用,wait方法释放锁,notify方法不释放锁。并且在这个例子中必须是Thread2先执行才可以。

  1. package com.ietree.multithread.sync;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. public class ListAdd3 {
  7. private volatile static List list = new ArrayList();
  8.  
  9. public void add() {
  10. list.add("apple");
  11. }
  12.  
  13. public int size() {
  14. return list.size();
  15. }
  16.  
  17. public static void main(String[] args) {
  18.  
  19. final ListAdd2 list2 = new ListAdd2();
  20.  
  21. // 1 实例化出来一个 lock
  22. // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用
  23. final Object lock = new Object();
  24.  
  25. Thread t1 = new Thread(new Runnable() {
  26. @Override
  27. public void run() {
  28. try {
  29. synchronized (lock) {
  30. for (int i = 0; i < 10; i++) {
  31. list2.add();
  32. System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
  33. Thread.sleep(500);
  34. if (list2.size() == 5) {
  35. System.out.println("已经发出通知..");
    //不释放锁,遇到size=5时还是继续执行
  36. lock.notify();
  37. }
  38. }
  39. }
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. }
  43.  
  44. }
  45. }, "t1");
  46.  
  47. Thread t2 = new Thread(new Runnable() {
  48. @Override
  49. public void run() {
  50. synchronized (lock) {
  51. if (list2.size() != 5) {
  52. try {
    //释放锁,让其他线程执行
  53. lock.wait();
  54. } catch (InterruptedException e) {
  55. e.printStackTrace();
  56. }
  57. }
  58. System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
  59. throw new RuntimeException();
  60. }
  61. }
  62. }, "t2");
  63.  
  64. t2.start();
  65. t1.start();
  66.  
  67. }
  68. }

程序输出:

  1. 当前线程:t1添加了一个元素..
  2. 当前线程:t1添加了一个元素..
  3. 当前线程:t1添加了一个元素..
  4. 当前线程:t1添加了一个元素..
  5. 当前线程:t1添加了一个元素..
  6. 已经发出通知..
  7. 当前线程:t1添加了一个元素..
  8. 当前线程:t1添加了一个元素..
  9. 当前线程:t1添加了一个元素..
  10. 当前线程:t1添加了一个元素..
  11. 当前线程:t1添加了一个元素..
  12. 当前线程:t2收到通知线程停止..
  13. Exception in thread "t2" java.lang.RuntimeException
  14. at com.ietree.multithread.sync.ListAdd3$2.run(ListAdd3.java:59)
  15. at java.lang.Thread.run(Unknown Source)

三、使用CountDownLatch类来实现多线程中线程之间的实时通信

  1. package com.ietree.multithread.sync;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.concurrent.CountDownLatch;
  6.  
  7. public class ListAdd2 {
  8. private volatile static List list = new ArrayList();
  9.  
  10. public void add() {
  11. list.add("apple");
  12. }
  13.  
  14. public int size() {
  15. return list.size();
  16. }
  17.  
  18. public static void main(String[] args) {
  19.  
  20. final ListAdd2 list2 = new ListAdd2();
  21.  
  22. final CountDownLatch countDownLatch = new CountDownLatch(1);
  23.  
  24. Thread t1 = new Thread(new Runnable() {
  25. @Override
  26. public void run() {
  27. try {
  28. for (int i = 0; i < 10; i++) {
  29. list2.add();
  30. System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
  31. Thread.sleep(500);
  32. if (list2.size() == 5) {
  33. System.out.println("已经发出通知..");
  34. countDownLatch.countDown();
  35. }
  36. }
  37. // }
  38. } catch (InterruptedException e) {
  39. e.printStackTrace();
  40. }
  41.  
  42. }
  43. }, "t1");
  44.  
  45. Thread t2 = new Thread(new Runnable() {
  46. @Override
  47. public void run() {
  48. if (list2.size() != 5) {
  49. try {
  50. countDownLatch.await();
  51. } catch (InterruptedException e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
  56. throw new RuntimeException();
  57. }
  58. }, "t2");
  59.  
  60. t2.start();
  61. t1.start();
  62.  
  63. }
  64. }

程序输出:

  1. 当前线程:t1添加了一个元素..
  2. 当前线程:t1添加了一个元素..
  3. 当前线程:t1添加了一个元素..
  4. 当前线程:t1添加了一个元素..
  5. 当前线程:t1添加了一个元素..
  6. 已经发出通知..
  7. Exception in thread "t2" 当前线程:t1添加了一个元素..
  8. 当前线程:t2收到通知线程停止..
  9. java.lang.RuntimeException
  10. at com.ietree.multithread.sync.ListAdd2$2.run(ListAdd2.java:56)
  11. at java.lang.Thread.run(Unknown Source)
  12. 当前线程:t1添加了一个元素..
  13. 当前线程:t1添加了一个元素..
  14. 当前线程:t1添加了一个元素..
  15. 当前线程:t1添加了一个元素..

四、使用多线程模拟一个队列

  1. package com.ietree.multithread.sync;
  2.  
  3. import java.util.LinkedList;
  4. import java.util.concurrent.TimeUnit;
  5. import java.util.concurrent.atomic.AtomicInteger;
  6.  
  7. public class MyQueue {
  8.  
  9. // 1、定义一个盛装元素集合
  10. private LinkedList<Object> list = new LinkedList<Object>();
  11.  
  12. // 2、定义一个计数器
  13. private AtomicInteger count = new AtomicInteger();
  14.  
  15. // 3、指定上限和下限
  16. private final int minSize = 0;
  17. private final int maxSize;
  18.  
  19. // 4、构造方法初始化大小
  20. public MyQueue(int size) {
  21. this.maxSize = size;
  22. }
  23.  
  24. // 5、初始化一个对象用于加锁
  25. private Object lock = new Object();
  26.  
  27. // put(anObject): 把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断,直到BlockingQueue里面有空间再继续.
  28. public void put(Object obj) {
  29. synchronized (lock) {
  30. if (count.get() == this.maxSize) {
  31. try {
  32. lock.wait();
  33. } catch (InterruptedException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. // 1、加入元素
  38. list.add(obj);
  39. // 2、计数器累加
  40. count.incrementAndGet();
  41. // 3、通知(唤醒)另外一个线程
  42. lock.notify();
  43. System.out.println("新加入的元素为:" + obj);
  44. }
  45. }
  46.  
  47. // take: 取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入.
  48. public Object take() {
  49. Object ret = null;
  50. synchronized (lock) {
  51. while (count.get() == this.minSize) {
  52. try {
  53. lock.wait();
  54. } catch (InterruptedException e) {
  55. e.printStackTrace();
  56. }
  57. }
  58. // 1、做移除元素操作
  59. ret = list.removeFirst();
  60. // 2、计数器作递减操作
  61. count.decrementAndGet();
  62. // 3、唤醒另外一个操作
  63. lock.notify();
  64. }
  65.  
  66. return ret;
  67. }
  68.  
  69. // 获取长度
  70. public int getSize() {
  71. return this.count.get();
  72. }
  73.  
  74. public static void main(String[] args) {
  75.  
  76. final MyQueue mq = new MyQueue(5);
  77. mq.put("a");
  78. mq.put("b");
  79. mq.put("c");
  80. mq.put("d");
  81. mq.put("e");
  82.  
  83. System.out.println("当前容器的长度:" + mq.getSize());
  84.  
  85. Thread t1 = new Thread(new Runnable() {
  86. @Override
  87. public void run() {
  88. mq.put("f");
  89. mq.put("g");
  90. }
  91. }, "t1");
  92.  
  93. t1.start();
  94.  
  95. Thread t2 = new Thread(new Runnable() {
  96. @Override
  97. public void run() {
  98. Object o1 = mq.take();
  99. System.out.println("移除的元素为:" + o1);
  100. Object o2 = mq.take();
  101. System.out.println("移除的元素为:" + o2);
  102. }
  103. }, "t2");
  104.  
  105. try {
  106. TimeUnit.SECONDS.sleep(2);
  107. } catch (InterruptedException e) {
  108. e.printStackTrace();
  109. }
  110.  
  111. t2.start();
  112. }
  113. }

程序输出:

  1. 新加入的元素为:a
  2. 新加入的元素为:b
  3. 新加入的元素为:c
  4. 新加入的元素为:d
  5. 新加入的元素为:e
  6. 当前容器的长度:5
  7. 移除的元素为:a
  8. 移除的元素为:b
  9. 新加入的元素为:f
  10. 新加入的元素为:g

Java多线程中线程间的通信的更多相关文章

  1. java多线程与线程间通信

    转自(http://blog.csdn.net/jerrying0203/article/details/45563947) 本文学习并总结java多线程与线程间通信的原理和方法,内容涉及java线程 ...

  2. JAVA多线程之线程间的通信方式

    (转发) 收藏 记 周日,北京的天阳光明媚,9月,北京的秋格外肃穆透彻,望望窗外的湛蓝的天,心似透过栏杆,沐浴在这透亮清澈的蓝天里,那朵朵白云如同一朵棉絮,心意畅想....思绪外扬, 鱼和熊掌不可兼得 ...

  3. iOS开发多线程篇—线程间的通信

    iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...

  4. Java——多线程之线程间通信

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

  5. Java多线程编程-线程之间的通信

    转载自:这里 学习了基础的线程知识 看到了 线程之间的通信 线程之间有哪些通信方式呢? 1.同步 这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信. public ...

  6. Java多线程基础——线程间通信

    在使用多线程的时候,经常需要多个线程进行协作来完成一件事情.在前面两章分析了Java多线程的基本使用以及利用synchronized来实现多个线程同步调用方法或者执行代码块.但上面两章的内容涉及到的例 ...

  7. Java多线程:线程间通信之volatile与sychronized

    由前文Java内存模型我们熟悉了Java的内存工作模式和线程间的交互规范,本篇从应用层面讲解Java线程间通信. Java为线程间通信提供了三个相关的关键字volatile, synchronized ...

  8. Java多线程:线程间通信之Lock

    Java 5 之后,Java在内置关键字sychronized的基础上又增加了一个新的处理锁的方式,Lock类. 由于在Java线程间通信:volatile与sychronized中,我们已经详细的了 ...

  9. java多线程:线程间通信——生产者消费者模型

    一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是,多个线程之间如何协作呢? 我们看一个仓库 ...

随机推荐

  1. 浅谈jquery插件开发模式

    首先根据<jQuery高级编程>的描述来看,jQuery插件开发方式主要有三种: 通过$.extend()来扩展jQuery 通过$.fn 向jQuery添加新的方法 通过$.widget ...

  2. 丑数(USACO)

    这个题是一个动态规划加优化的经典题 1246 丑数 USACO  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解 题目描述 Description 对 ...

  3. 完全关闭IIS日志,包括System32下的LogFile

    早上突然发现网站访问不了了,登陆服务器一看,是C盘满了. 查一看,是IIS产生了70多G的日志,但明明已关闭日志了,还是会产生. 产生的目录在:C:\Windows\System32\LogFiles ...

  4. 整理:20个非常有用的Java程序片段

    下面是20个非常有用的Java程序片段,希望能对你有用. 1. 字符串有整型的相互转换 String a = String.valueOf(2); //integer to numeric strin ...

  5. jsonp原生js代码示例

    /* mightygumball.js */ /* * get the content of a JSON file using JSONP * update every 3 seconds. * * ...

  6. c++学习笔记之封装篇(上)

    title: c++学习笔记之封装篇(上) date: 2017-03-12 18:59:01 tags: [c++,c,封装,类] categories: [学习,程序员,c/c++] --- 一. ...

  7. Kruskal算法的实现

    #include "stdio.h" #include "stdlib.h" struct edge { int m; int n; int d; }a[]; ...

  8. 我所理解的javascript中函数的作用域和作用域链

    本文为原创,转载请注明出处: cnzt       文章:cnzt-p 写在前面 一周木有更新了,今天终于攻克了自行车难关,非常开心,特意来一更~ (那些捂嘴偷笑的人我看到你们了快把嘴闭上我会假装没看 ...

  9. Spring+SpringMVC+MyBatis+easyUI整合优化篇(四)单元测试实例

    日常啰嗦 前一篇文章<Spring+SpringMVC+MyBatis+easyUI整合优化篇(三)代码测试>讲了不为和不能两个状态,针对不为,只能自己调整心态了,而对于不能,本文会结合一 ...

  10. 用Caffe生成对抗样本

    同步自我的知乎专栏:https://zhuanlan.zhihu.com/p/26122612 上篇文章 瞎谈CNN:通过优化求解输入图像 - 知乎专栏 中提到过对抗样本,这篇算是针对对抗样本的一个小 ...