多线程通信(wait和notify)
线程通信概念:
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体的必用方式之一。当线程存在通信指挥,系统间的交互性会更强大,在提高CPU利用率的同时还会使开发人员对线程任务在处理的过程中进行有效的把控与监督。
使用wait/notify方法实现线程间的通信。(注意这两个方法都是object的类的方法,换句话说java为所有的对象都提供了这两个方法)
1 wait和notify必须配合synchronized关键字使用
2wait方法释放锁,notify方法不释放锁
下面看一段demo:
public class ListAdd1 {
private volatile static List list = new ArrayList(); public void add() {
list.add("bjsxt");
} public int size() {
return list.size();
} public static void main(String[] args) {
final ListAdd1 list1 = new ListAdd1();
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();
}
}
首先看一下运行结果:
在第一个线程运行到list.size()=5的时候,停止t2线程,这种实现方式非常不好,需要t2线程一直去轮询。
可以使用java里面线程通信的方式去实现及重构上面的这种方式。下面我们看另外一个demo:
public class ListAdd2 {
private volatile static List list = new ArrayList(); public void add() {
list.add("bjsxt");
} public int size() {
return list.size();
} public static void main(String[] args) {
//实例化出来一个lock
//当使用 wait 和 notify 的时候,一定要配合着synchronized关键字去使用
final Object lock = new Object();
final ListAdd2 list2 = new ListAdd2();
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("已经发出通知、、");
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();
}
} 先看一下运行的结果:
他是先打印5个结果,然后发出通知,接着又执行5个元素,这个时候t2才接收到通知,说明这种方式是不具备实时性的,
看一下,这个线程是先启动t2的,首先是t2获取锁,然后等t2wait,这个时候,t2线程释放锁,此时,t1线程获得锁,
然后在list2.size()等于5的时候,调用notify方法,notify方法是不释放锁的,所以t2线程获取不到锁,这个时候,只能等待t1线程执行完,t2线程才能获取锁,进行业务处理。这也就是打印结果是这样的原因。
加入t1和t2换个位置的话,会造成t1获得锁,然后t2就不能获得锁,等t1执行完,list.size()直接就等于10了,然后才会运行t2线程。
弊端:一定要等待t1线程结束后,才能执行另外一个等待的线程,不具备实时性。
下面看一个解决这个弊端的demo:
public class ListAdd3 {
private volatile static List list = new ArrayList(); public void add() {
list.add("bjsxt");
} public int size() {
return list.size();
} public static void main(String[] args) {
final ListAdd3 list3 = new ListAdd3();
//括号里面是传递的个数
final CountDownLatch countDownLatch = new CountDownLatch(1);
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
list3.add();
System.out.println("当前线程: " + Thread.currentThread().getName()
+ "添加了一个元素。。");
Thread.sleep(500);
if (list3.size() == 5) {
System.out.println("已经发出通知、、");
countDownLatch.countDown();//类似于notify
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
if (list3.size() != 5) {
try {
countDownLatch.await();//类似于wait
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("当前线程: " + Thread.currentThread().getName()
+ " 收到通知线程停止");
throw new RuntimeException();
} }, "t2");
t2.start();
t1.start();
}
}
看一下运行结果:
这就实现了线程通信间的实时性。括号里面的数字代表着下面的t1线程里面有几个countDown,具体相关的知识点,以后在分析。
多线程通信(wait和notify)的更多相关文章
- 多线程通信(wait/notify)
线程通信概念:线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体的必用方式之一.当线程存在通信指挥,系统间的交互性会更强大,在提高CPU利用率的同时就 ...
- 多线程一共就俩问题:1.线程安全(访问共享数据) 2.线程通信(wait(),notify())
多线程一共就俩问题:1.线程安全(访问共享数据) 2.线程通信(wait(),notify()) 1.线程安全,无非就是加锁,访问共享资源时,synchronized 2.线程通信,就是控制各个线程之 ...
- 母鸡下蛋实例:多线程通信生产者和消费者wait/notify和condition/await/signal条件队列
简介 多线程通信一直是高频面试考点,有些面试官可能要求现场手写生产者/消费者代码来考察多线程的功底,今天我们以实际生活中母鸡下蛋案例用代码剖析下实现过程.母鸡在鸡窝下蛋了,叫练从鸡窝里把鸡蛋拿出来这个 ...
- JAVA多线程通信
JAVA多线程通信 package com.frank.thread; /** * author:pengyan * date:Jun 16, 2011 * file:ProducerAndCusto ...
- 多线程协作wait、notify、notifyAll方法简介理解使用 多线程中篇(十四)
在锁与监视器中有对wait和notify以及notifyAll进行了简单介绍 所有对象都有一个与之关联的锁与监视器 wait和notify以及notifyAll之所以是Object的方法就是因为任何一 ...
- 多线程通信的两种方式? (可重入锁ReentrantLock和Object)
(一)Java中线程协作的最常见的两种方式: (1)利用Object的wait().notify()和notifyAll()方法及synchronized (2)使用Condition.Reentra ...
- 8.并发编程--多线程通信-wait-notify-模拟Queue
并发编程--多线程通信-wait-notify-模拟Queue 1. BlockingQueue 顾名思义,首先是一个队列,其次支持阻塞的机制:阻塞放入和获取队列中的数据. 如何实现这样一个队列: 要 ...
- 7.并发编程--多线程通信-wait-notify
并发编程--多线程通信-wait-notify 多线程通信:线程通信的目的是为了能够让线程之间相互发送信号; 1. 多线程通信: 线程通信的目的是为了能够让线程之间相互发送信号.另外,线程通信还能够使 ...
- Android多线程通信机制
掌握Android的多线程通信机制,我们首先应该掌握Android中进程与线程是什么. 1. 进程 在Android中,一个应用程序就是一个独立的进程(应用运行在一个独立的环境中,可以避免其他应用程序 ...
随机推荐
- react-native-picker 实现省市区 时间日期组件
github示例以及详细参数:https://github.com/beefe/react-native-picker 先 安装 link npm install react-native-picke ...
- li直接1px 像素的原因
1.由于空白节点(多由于Enter造成),li不换行就可以解决问题. Internet Explorer会忽略节点之间生成的空白节点,其它浏览器不会忽略(可以通过检测节点类型,过滤子节点) 2.完美解 ...
- js判断对象
一般学java的小伙伴,刚开始写js时如果遇到要判断一个字符串是否不为空,往往会这样写 if(str != undefined && str != null && st ...
- Zabbix笔记
简单检查中的icmppingloss[<target>,<packets>,<interval>,<size>,<timeout>] 结 ...
- 使用xshell xftp连接centos的过程。
1 配置网络 登录Centtos系统,配置网卡. cd 空格/etc/sysconfig/network-scripts 回车键. ls 查看文件 vi ifcig-eth0 编辑这个文件 修改为 ...
- ps记录
图层 ctrl+j:通过拷贝的图层 颜色填充 alt+delete:前景色填充(或alt+backspace) ctrl+delete:背景色填充(或ctrl+backspace) 多图层合并一 分组 ...
- scala case类
case类 case class Person(name:String) case 类有如下特点: 1. 构造参数默认是 val 的. 2. case 类实例化对象的时候,不需要 new 关键字.因为 ...
- 梯度迭代树(GBDT)算法原理及Spark MLlib调用实例(Scala/Java/python)
梯度迭代树(GBDT)算法原理及Spark MLlib调用实例(Scala/Java/python) http://blog.csdn.net/liulingyuan6/article/details ...
- hdu2669-Romantic-(扩展欧几里得定理)
Romantic Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- CSS 规范 命名规则
http://nec.netease.com/standard/css-practice.html