一、使用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多线程中线程间的通信的更多相关文章

  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. Levenshtein distance 编辑距离

    编辑距离,又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符 实现方案: 1. 找出最长 ...

  2. ConfigParser-- 读取写入配置文件

    基础读取配置文件   -read(filename)               直接读取文件内容 -sections()                      得到所有的section,并以列表 ...

  3. 部署Cloudera Management for centos 7

    hadoop生态圈框架工具甚多,自己整合起来很是繁琐,特别是oozie以及hue结合来实现hive.mr.spark等定时依赖任务更是一步一个坑,为了减少踩坑,只好从apache hadoop,转向C ...

  4. 【树莓派】Linux 测网速及树莓派源

    这篇文章比较杂,其中包含三点:linux环境中测试网络速度,树莓派下载软件的源,部分我写好的脚本: 一.Linux 测网速 Linux 测网速: sar -n DEV 1 100 1代表一秒统计并显示 ...

  5. Sublime Text3 编辑器我的最爱

    简介 Sublime Text 3是一个神奇的文本编辑器,适合程序员.作家.它有很多亮点功能,比如多选择.Go Anything.命令面板.多选择可以让你同时编辑多出代码,Got Anything 像 ...

  6. firefox无法使用yslow的解决方案

    首先,Yslow不支持firefox 36及以上版本. 解决方案:使用yslow的书签版本 使用方法:1.访问这里 http://yslow.org/mobile/ 2.把页面最后的那个 Deskto ...

  7. 大数据量场景下storm自定义分组与Hbase预分区完美结合大幅度节省内存空间

    前言:在系统中向hbase中插入数据时,常常通过设置region的预分区来防止大数据量插入的热点问题,提高数据插入的效率,同时可以减少当数据猛增时由于Region split带来的资源消耗.大量的预分 ...

  8. shell是什么,各种shell的初步认识,适用于初学者

    shell是什么?有什么用处?怎么用?我相信,这是大部分人刚接触到shell都有过的疑问.下面小编为大家讲解一下自己的讲解,希望能对大家有所帮助. 什么是shell? shell就是系统内核的一层壳, ...

  9. win7下nsis打包exe安装程序教程

    下载软件包: NSIS中文版 :https://pan.baidu.com/s/1mitSQU0 装好之后会出现两个软件:Nullsoft Install System 和 VNISEdit 编译环境 ...

  10. 老李回答:JAVA程序的性能测试方法

    Java 1.5以上都在虚拟机里内建了程序性能跟踪的功能,并提供了Java Profiling API,简称JPA,你可以搜索'java profiling'.Java也提供了简单的性能性能跟踪工具J ...