Java多线程中线程间的通信
一、使用while方式来实现线程之间的通信
- package com.ietree.multithread.sync;
- import java.util.ArrayList;
- import java.util.List;
- public class MyList {
- private volatile static List list = new ArrayList();
- public void add() {
- list.add("apple");
- }
- public int size() {
- return list.size();
- }
- public static void main(String[] args) {
- final MyList list1 = new MyList();
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- for (int i = 0; i < 10; i++) {
- list1.add();
- System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
- Thread.sleep(500);
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "t1");
- Thread t2 = new Thread(new Runnable() {
- @Override
- public void run() {
- while (true) {
- if (list1.size() == 5) {
- System.out.println("当前线程收到通知:" + Thread.currentThread().getName() + " list size = 5 线程停止..");
- throw new RuntimeException();
- }
- }
- }
- }, "t2");
- t1.start();
- t2.start();
- }
- }
程序输出:
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- Exception in thread "t2" 当前线程收到通知:t2 list size = 5 线程停止..
- java.lang.RuntimeException
- at com.ietree.multithread.sync.MyList$2.run(MyList.java:43)
- at java.lang.Thread.run(Unknown Source)
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
理解:线程Thread2不停地通过while语句检测这个条件(list.size()==5)是否成立 ,从而实现了线程间的通信。但是这种方式会浪费CPU资源。
二、wait notfiy 方法实现多线程中线程之间的通信
使用这种方式实现线程通信需要注意:wait和notify必须配合synchronized关键字使用,wait方法释放锁,notify方法不释放锁。并且在这个例子中必须是Thread2先执行才可以。
- package com.ietree.multithread.sync;
- import java.util.ArrayList;
- import java.util.List;
- public class ListAdd3 {
- private volatile static List list = new ArrayList();
- public void add() {
- list.add("apple");
- }
- public int size() {
- return list.size();
- }
- public static void main(String[] args) {
- final ListAdd2 list2 = new ListAdd2();
- // 1 实例化出来一个 lock
- // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用
- final Object lock = new Object();
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (lock) {
- for (int i = 0; i < 10; i++) {
- list2.add();
- System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
- Thread.sleep(500);
- if (list2.size() == 5) {
- System.out.println("已经发出通知..");
//不释放锁,遇到size=5时还是继续执行- lock.notify();
- }
- }
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "t1");
- Thread t2 = new Thread(new Runnable() {
- @Override
- public void run() {
- synchronized (lock) {
- if (list2.size() != 5) {
- try {
//释放锁,让其他线程执行- lock.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
- throw new RuntimeException();
- }
- }
- }, "t2");
- t2.start();
- t1.start();
- }
- }
程序输出:
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 已经发出通知..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t2收到通知线程停止..
- Exception in thread "t2" java.lang.RuntimeException
- at com.ietree.multithread.sync.ListAdd3$2.run(ListAdd3.java:59)
- at java.lang.Thread.run(Unknown Source)
三、使用CountDownLatch类来实现多线程中线程之间的实时通信
- package com.ietree.multithread.sync;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.concurrent.CountDownLatch;
- public class ListAdd2 {
- private volatile static List list = new ArrayList();
- public void add() {
- list.add("apple");
- }
- public int size() {
- return list.size();
- }
- public static void main(String[] args) {
- final ListAdd2 list2 = new ListAdd2();
- final CountDownLatch countDownLatch = new CountDownLatch(1);
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- for (int i = 0; i < 10; i++) {
- list2.add();
- System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
- Thread.sleep(500);
- if (list2.size() == 5) {
- System.out.println("已经发出通知..");
- countDownLatch.countDown();
- }
- }
- // }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "t1");
- Thread t2 = new Thread(new Runnable() {
- @Override
- public void run() {
- if (list2.size() != 5) {
- try {
- countDownLatch.await();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
- throw new RuntimeException();
- }
- }, "t2");
- t2.start();
- t1.start();
- }
- }
程序输出:
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 已经发出通知..
- Exception in thread "t2" 当前线程:t1添加了一个元素..
- 当前线程:t2收到通知线程停止..
- java.lang.RuntimeException
- at com.ietree.multithread.sync.ListAdd2$2.run(ListAdd2.java:56)
- at java.lang.Thread.run(Unknown Source)
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
- 当前线程:t1添加了一个元素..
四、使用多线程模拟一个队列
- package com.ietree.multithread.sync;
- import java.util.LinkedList;
- import java.util.concurrent.TimeUnit;
- import java.util.concurrent.atomic.AtomicInteger;
- public class MyQueue {
- // 1、定义一个盛装元素集合
- private LinkedList<Object> list = new LinkedList<Object>();
- // 2、定义一个计数器
- private AtomicInteger count = new AtomicInteger();
- // 3、指定上限和下限
- private final int minSize = 0;
- private final int maxSize;
- // 4、构造方法初始化大小
- public MyQueue(int size) {
- this.maxSize = size;
- }
- // 5、初始化一个对象用于加锁
- private Object lock = new Object();
- // put(anObject): 把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断,直到BlockingQueue里面有空间再继续.
- public void put(Object obj) {
- synchronized (lock) {
- if (count.get() == this.maxSize) {
- try {
- lock.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- // 1、加入元素
- list.add(obj);
- // 2、计数器累加
- count.incrementAndGet();
- // 3、通知(唤醒)另外一个线程
- lock.notify();
- System.out.println("新加入的元素为:" + obj);
- }
- }
- // take: 取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入.
- public Object take() {
- Object ret = null;
- synchronized (lock) {
- while (count.get() == this.minSize) {
- try {
- lock.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- // 1、做移除元素操作
- ret = list.removeFirst();
- // 2、计数器作递减操作
- count.decrementAndGet();
- // 3、唤醒另外一个操作
- lock.notify();
- }
- return ret;
- }
- // 获取长度
- public int getSize() {
- return this.count.get();
- }
- public static void main(String[] args) {
- final MyQueue mq = new MyQueue(5);
- mq.put("a");
- mq.put("b");
- mq.put("c");
- mq.put("d");
- mq.put("e");
- System.out.println("当前容器的长度:" + mq.getSize());
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- mq.put("f");
- mq.put("g");
- }
- }, "t1");
- t1.start();
- Thread t2 = new Thread(new Runnable() {
- @Override
- public void run() {
- Object o1 = mq.take();
- System.out.println("移除的元素为:" + o1);
- Object o2 = mq.take();
- System.out.println("移除的元素为:" + o2);
- }
- }, "t2");
- try {
- TimeUnit.SECONDS.sleep(2);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- t2.start();
- }
- }
程序输出:
- 新加入的元素为:a
- 新加入的元素为:b
- 新加入的元素为:c
- 新加入的元素为:d
- 新加入的元素为:e
- 当前容器的长度:5
- 移除的元素为:a
- 移除的元素为:b
- 新加入的元素为:f
- 新加入的元素为:g
Java多线程中线程间的通信的更多相关文章
- java多线程与线程间通信
转自(http://blog.csdn.net/jerrying0203/article/details/45563947) 本文学习并总结java多线程与线程间通信的原理和方法,内容涉及java线程 ...
- JAVA多线程之线程间的通信方式
(转发) 收藏 记 周日,北京的天阳光明媚,9月,北京的秋格外肃穆透彻,望望窗外的湛蓝的天,心似透过栏杆,沐浴在这透亮清澈的蓝天里,那朵朵白云如同一朵棉絮,心意畅想....思绪外扬, 鱼和熊掌不可兼得 ...
- iOS开发多线程篇—线程间的通信
iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...
- Java——多线程之线程间通信
Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...
- Java多线程编程-线程之间的通信
转载自:这里 学习了基础的线程知识 看到了 线程之间的通信 线程之间有哪些通信方式呢? 1.同步 这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信. public ...
- Java多线程基础——线程间通信
在使用多线程的时候,经常需要多个线程进行协作来完成一件事情.在前面两章分析了Java多线程的基本使用以及利用synchronized来实现多个线程同步调用方法或者执行代码块.但上面两章的内容涉及到的例 ...
- Java多线程:线程间通信之volatile与sychronized
由前文Java内存模型我们熟悉了Java的内存工作模式和线程间的交互规范,本篇从应用层面讲解Java线程间通信. Java为线程间通信提供了三个相关的关键字volatile, synchronized ...
- Java多线程:线程间通信之Lock
Java 5 之后,Java在内置关键字sychronized的基础上又增加了一个新的处理锁的方式,Lock类. 由于在Java线程间通信:volatile与sychronized中,我们已经详细的了 ...
- java多线程:线程间通信——生产者消费者模型
一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是,多个线程之间如何协作呢? 我们看一个仓库 ...
随机推荐
- 浅谈jquery插件开发模式
首先根据<jQuery高级编程>的描述来看,jQuery插件开发方式主要有三种: 通过$.extend()来扩展jQuery 通过$.fn 向jQuery添加新的方法 通过$.widget ...
- 丑数(USACO)
这个题是一个动态规划加优化的经典题 1246 丑数 USACO 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 对 ...
- 完全关闭IIS日志,包括System32下的LogFile
早上突然发现网站访问不了了,登陆服务器一看,是C盘满了. 查一看,是IIS产生了70多G的日志,但明明已关闭日志了,还是会产生. 产生的目录在:C:\Windows\System32\LogFiles ...
- 整理:20个非常有用的Java程序片段
下面是20个非常有用的Java程序片段,希望能对你有用. 1. 字符串有整型的相互转换 String a = String.valueOf(2); //integer to numeric strin ...
- jsonp原生js代码示例
/* mightygumball.js */ /* * get the content of a JSON file using JSONP * update every 3 seconds. * * ...
- c++学习笔记之封装篇(上)
title: c++学习笔记之封装篇(上) date: 2017-03-12 18:59:01 tags: [c++,c,封装,类] categories: [学习,程序员,c/c++] --- 一. ...
- Kruskal算法的实现
#include "stdio.h" #include "stdlib.h" struct edge { int m; int n; int d; }a[]; ...
- 我所理解的javascript中函数的作用域和作用域链
本文为原创,转载请注明出处: cnzt 文章:cnzt-p 写在前面 一周木有更新了,今天终于攻克了自行车难关,非常开心,特意来一更~ (那些捂嘴偷笑的人我看到你们了快把嘴闭上我会假装没看 ...
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(四)单元测试实例
日常啰嗦 前一篇文章<Spring+SpringMVC+MyBatis+easyUI整合优化篇(三)代码测试>讲了不为和不能两个状态,针对不为,只能自己调整心态了,而对于不能,本文会结合一 ...
- 用Caffe生成对抗样本
同步自我的知乎专栏:https://zhuanlan.zhihu.com/p/26122612 上篇文章 瞎谈CNN:通过优化求解输入图像 - 知乎专栏 中提到过对抗样本,这篇算是针对对抗样本的一个小 ...