Java 之多线程通信(等待/唤醒)
多线程间通信: 多个线程在处理同一个资源, 但是任务却不同.
等待/唤醒机制
- 涉及的方法
wait(): 让线程处于冻结状态, 被 wait() 的线程会被存储到线程池中notify(): 唤醒线程池中的任意一个线程notifyAll(): 唤醒线程池中所有的线程
- 这些方法必须定义在同步中, 因为这些方法是用于操作线程状态的方法, 必须要明确到底
操作的是哪个锁上的线程. - 为什么操作线程的方法 wait(), notify(), notifyAll() 定义在了 Object 类中?
因为这些方法是监视方法, 监视器其实就是锁. 而锁可以是任意的对象, 任意对象都能调用的方法一定
定义在 Object 类中.

// 资源
class Resource
{
String name;
String sex;
boolean flag = false;
}
// 输入线程
class Input implements Runnable
{
Resource r;
// 带参数的构造函数, 以确保输入和输出操作的是同一个资源
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if(r.flag)
//该异常只能捕获, 不能抛出, 因为父类 Runnable 中 run() 方法没有异常
try{r.wait();}catch(InterruptedException e){}
if(x==0)
{
r.name = "mike";
r.sex = "nan";
}
else
{
r.name = "丽丽";
r.sex = "girlgirlgirl";
}
r.flag = true;
r.notify();
}
x = (x+1)%2; // 改变 x 的值, 获得不同的输入值
}
}
}
class Output implements Runnable
{
Resource r;
// 带参数的构造函数, 确保输入和输出线程操作的是同一个资源
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r) // 以资源对象作为锁, 输入线程和输出线程使用的为同一个锁
{
if(!r.flag)
try{r.wait();}catch(InterruptedException e){}
System.out.println(r.name + "......" + r.sex);
r.flag = flase;
r.notify();
}
}
}
}
class ResourceDemo
{
public static void main(String[] args)
{
// 创建资源
Resource r = new Resource();
// 创建任务
Input in = new Input(r); // 使用带参数的构造函数初始化, 确保操作的为同一个资源 r
Output out = new Output(r); //使用带参数的构造函数初始化, 确保操作的为同一个资源 r
// 创建线程
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
// 开启线程
t1.start();
t2.start();
}
}
<--------------------分隔线--------------------------------->
// 将属性私有化, 升级版
class Resource
{
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name, String sex) //使用同步函数
{
if(flag)
try{this.wait();}catch(InterruptedException e){}
this.name = name;
this.sex = sex;
flag = true;
this.notify(); // 这时候的锁是 this
}
public synchronized void out()
{
if(!flag)
try{this.wait();}catch(InterruptedException e){}
System.out.println(name+"....."+sex);
flag = false;
this.notify();
}
}
class Input implements Runnable
{
Resource r;
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
if(x==0)
{
r.set("mike","nan");
}
else
{
r.set("lili","nvnv");
}
x = (x+1)%2;
}
}
}
class Output implements Runnable
{
Resource r;
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
- [JavaSE 基础视频(毕向东)](https://www.bilibili.com/video/av3106510/)
Java 之多线程通信(等待/唤醒)的更多相关文章
- Java 实现多线程切换等待唤醒交替打印奇偶数
引言 在日常工作生活中,可能会有用时几个人或是很多人干同一件事,在java编程中,同样也会出现类似的情况,多个线程干同样一个活儿,比如火车站买票系统不能多个人买一到的是同一张票,当某个窗口(线程)在卖 ...
- java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)
*java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...
- java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)
1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以 ...
- java 22 - 17 多线程之等待唤醒机制(接16)
先来一张图,看看什么叫做等待唤醒机制 接上一章的例子. 例子:学生信息的录入和获取 * 资源类:Student * 设置学生数据:SetThread(生产者) * 获取学生数据:GetThread( ...
- Java第二十五天,多线程之等待唤醒机制
当线程被创建并且被启动之后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,而是具有以下多种状态: 这六种状态之间的转换关系如下: 1.等待唤醒机制 注意: (1)两个线程之间必须用同步代码块 ...
- java多线程的等待唤醒机制及如何解决同步过程中的安全问题
/* class Person{ String name; String sex; boolean flag = true; public void setPerson(String name, St ...
- Java 线程间通信 —— 等待 / 通知机制
本文部分摘自<Java 并发编程的艺术> volatile 和 synchronize 关键字 每个处于运行状态的线程,如果仅仅是孤立地运行,那么它产生的作用很小,如果多个线程能够相互配合 ...
- Java中的等待唤醒机制—至少50%的工程师还没掌握!
这是一篇走心的填坑笔记,自学Java的几年总是在不断学习新的技术,一路走来发现自己踩坑无数,而填上的坑却屈指可数.突然发现,有时候真的不是几年工作经验的问题,有些东西即使工作十年,没有用心去学习过也不 ...
- 多线程之Java中的等待唤醒机制
多线程的问题中的经典问题是生产者和消费者的问题,就是如何让线程有序的进行执行,获取CPU执行时间片的过程是随机的,如何能够让线程有序的进行,Java中提供了等待唤醒机制很好的解决了这个问题! 生产者消 ...
随机推荐
- 点滴积累【C#】---使用log4net组件记录错误日志(以文本形式记录)
效果: 描述: 利用log4net组件进行错误日志的记录,log4net记录错误的方式我所了解的有4种,No.1 文本形式记录日志,No.2存储到数据库形式记录日志,No.3控制台控制显示日志,No. ...
- Oracle Restart能够用来给Oracle GoldenGate 做 High Availability 使用么?
Oracle Restart能够用来给Oracle GoldenGate 做 High Availability 使用么? 来源于: Can Oracle Restart be used with ...
- DOCTYPE 与浏览器模式分析
DOCTYPE 的诞生 DOCTYPE,或者称为 Document Type Declaration(文档类型声明,缩写 DTD).通常情况下,DOCTYPE 位于一个 HTML 文档的最前面的位置, ...
- Android App常规测试内容
转自:https://mp.weixin.qq.com/s?__biz=MzU0NjcyNDg3Mw==&mid=2247484053&idx=1&sn=116fe8c7eed ...
- 0050 MyBatis关联映射--一对多关系
一对多关系更加常见,比如用户和订单,一个用户可以有多个订单 DROP TABLE IF EXISTS customer; /*用户表*/ CREATE TABLE customer( `pk` INT ...
- Ream的入门使用
一.介绍 Realm是一个不错的手机平台上的数据库,支持多种编程环境,如:Java.Object-C.React Native.Swift.Xamari等. Realm的官网:https://real ...
- linux学习笔记22---命令diff和diff3
diff 命令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方.diff在命令行中打印每一个行的改动.最新版本的diff还支持二进制文件.diff程序的 ...
- Unity3D 5中增加WebGL 播放插件
http://www.csdn.net/article/2014-03-18/2818822-Unity-5-game-engine 其实我是搞3d的,这篇文章里所有的术语看了都有很强的亲切感. Un ...
- VMware网络连接失败解决方法
假如你碰到了VMware 网络被断开,明明已经分配了适配器,客户端却显示网络断开没有连接. 一. 可用恢复默认的方法重置所有网卡及服务. 如图片操作: 进主工具首页.点击: 虚拟网络编辑器 然后点击下 ...
- (转)64位开源处理器Rocket的源代码简单介绍
转载地址: http://blog.csdn.net/leishangwen/article/details/46604819 最近大概阅读了一下UCB发布的Rocket处理器的源码,对源代码各个文件 ...