一、使用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. Linux screen 常用命令

    想必,只要接触过Linux一段时间的人,一定知道screen这个神奇的工具了,它主要有如下些优势: 1. 后台运行:当你在ssh terminal执行shell时,如果网络这时断开,你的程序会怎样?T ...

  2. QT Creator 快速入门教程 读书笔记(一)

    一 Qt简介 Qt 是一个跨平台的C++应用程序框架,支持Windows.Linux.Mac OS X.Android.iOS.Windows Phone.嵌入式系统等.也就是说,Qt 可以同时支持桌 ...

  3. 关于OOCSS的一点思考

    关于面向对象,自己是很熟悉了,不能说代码实际开发效果有多好,但是这个概念确实经常见,那么到底什么是面向对象? 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物---百度 ...

  4. 关于 Python generator(生成器)的类比

    Python 的生成器运用仿佛是最完美的 xing爱,生成器本身和循环代表男女,结束代表同时达到高潮,不是很精准,但很有趣啊!哈哈哈,一下记住了

  5. 老司机实战Windows Server Docker:5 Windows Server Dockerfile葵花宝典

    前面两篇(简单运维1.简单运维2)介绍了一些Windows Server Docker相关的基本运维知识.今天这一篇,Windows Server Dockerfile葵花宝典,涵盖了许多典型场景的W ...

  6. linux系统各种乱码问题

    linux系统乱码问题 最近使用ubuntu操作系统(客户端)在ssh连接linux服务器的时候发现乱码问题,但是本机查看中文显示中文没有问题,只是在使用终端more查看本地或远端gbk之类中文编码的 ...

  7. Alamofire源码解读系列(十一)之多表单(MultipartFormData)

    本篇讲解跟上传数据相关的多表单 前言 我相信应该有不少的开发者不明白多表单是怎么一回事,然而事实上,多表单确实很简单.试想一下,如果有多个不同类型的文件(png/txt/mp3/pdf等等)需要上传给 ...

  8. h5开发app之在线生成二维码

    h5通过jquery和qrcode在线生成二维码 首先我们需要下载一个qrcode.js文件,然后依次引入jquery和qrcode文件. 1.创建一个输入框以便做演示使用: <input id ...

  9. iOS 中的单例设计模式

    单例设计模式:在它的核心结构中只包含一个被称为单例类的特殊类.例如文件管理中的NSUserDefault,应用程序中的UIApplication,整个应用程序就这一个单例类,负责应用程序的一些操作,单 ...

  10. Luogu3373【模板】线段树2

    P3373[模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格式: 第一行 ...