多个线程在处理同一个资源,但是线程的任务却不相同,通过一定的手段使各个线程能有效地利用资源,

这种手段即:等待唤醒机制,又称作线程之间的通信

涉及到的方法:wait(),notify()

示例:

两个线程一个输入,一个输出

package demo;

public class Resource {
public String name;
public String sex;
}

输入线程:

package demo;

public class Input implements Runnable {
private Resource r = new Resource(); public void run() {
int i = 0;
while (true) {
if (i % 2 == 0) {
r.name = "张三";
r.sex = "男";
} else {
r.name = "李四";
r.sex = "女";
}
i++;
}
} }

输出线程:

package demo;

public class Output implements Runnable {
private Resource r = new Resource();
public void run(){
while (true) {
System.out.println(r.name+"..."+r.sex);
}
}
}

测试类:

package demo;

public class ThreadDemo {
public static void main(String[] args) {
Input in = new Input();
Output out = new Output();
Thread tin = new Thread(in);
Thread tout = new Thread(out); tin.start();
tout.start();
}
}

运行后却发现输出的都是null...null

因为输入线程和输出线程中创建的Resource对象使不同的

解决null问题:

package demo;

public class Input implements Runnable {
private Resource r; public Input(Resource r){
this.r = r;
} public void run() {
int i = 0;
while (true) {
if (i % 2 == 0) {
r.name = "张三";
r.sex = "男";
} else {
r.name = "李四";
r.sex = "女";
}
i++;
}
} }
package demo;

public class Output implements Runnable {
private Resource r; public Output(Resource r){
this.r = r;
} public void run(){
while (true) {
System.out.println(r.name+"..."+r.sex);
}
}
}
package demo;

public class ThreadDemo {
public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(r);
Output out = new Output(r);
Thread tin = new Thread(in);
Thread tout = new Thread(out); tin.start();
tout.start();
}
}

运行后又发现了另一个问题:

输出中含有:张三...女或者李四...男,性别出错

发生原因:

赋值完张三和男后,继续赋值李四和女,这时候还未还得及赋值女,就进入了输出线程,这时候就会输出李四...男

于是想到加上同步:

    public void run() {
int i = 0;
while (true) {
synchronized (this) {
if (i % 2 == 0) {
r.name = "张三";
r.sex = "男";
} else {
r.name = "李四";
r.sex = "女";
}
i++;
}
}
}
    public void run() {
while (true) {
synchronized (this) {
System.out.println(r.name + "..." + r.sex);
}
}
}

然而问题并没有解决:

原因:

这里的同步失去了作用,用到的不是一个锁

解决办法:

使用一个共同的锁即可

public void run() {
int i = 0;
while (true) {
synchronized (r) {
if (i % 2 == 0) {
r.name = "张三";
r.sex = "男";
} else {
r.name = "李四";
r.sex = "女";
}
i++;
}
}
}
    public void run() {
while (true) {
synchronized (r) {
System.out.println(r.name + "..." + r.sex);
}
}
}

这时候就是正常的输出了

但是还是存在一个问题,我们希望的是张三和李四交错出现,一个张三一个李四,现在依然是随机出现的,大片的张三或李四

解决办法:

先让input线程赋值,然后让output线程输出,并且让输入线程等待,不允许再赋值李四,等待输出张三结束后,再允许李四赋值,依次下去

输入线程也需要同样的方式,输出完后要等待

这时候就需要用到等待唤醒机制:

输入:赋值后,执行方法wait()永远等待

输出:打印后,再输出等待之前,唤醒输入notify(),自己再wait()永远等待

输入:被唤醒后,重新赋值,必须notify()唤醒输出的线程,自己再wait()等待

依次循环下去

代码实现:

package demo;

public class Resource {
public String name;
public String sex;
public boolean flag = false;
}
package demo;

public class Input implements Runnable {
private Resource r; public Input(Resource r) {
this.r = r;
} public void run() {
int i = 0;
while (true) {
synchronized (r) {
if (r.flag) {
try {
r.wait();
} catch (Exception e) {
}
}
if (i % 2 == 0) {
r.name = "张三";
r.sex = "男";
} else {
r.name = "李四";
r.sex = "女";
}
r.flag = true;
r.notify();
}
i++;
}
}
}
package demo;

public class Output implements Runnable {
private Resource r; public Output(Resource r) {
this.r = r;
} public void run() {
while (true) {
synchronized (r) {
if (!r.flag) {
try {
r.wait();
} catch (Exception e) {
}
}
System.out.println(r.name + "..." + r.sex);
r.flag = false;
r.notify();
}
}
}
}
package demo;

public class ThreadDemo {
public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(r);
Output out = new Output(r);
Thread tin = new Thread(in);
Thread tout = new Thread(out); tin.start();
tout.start();
}
}

这时候就是张三李四交错输出了

完成

Java学习笔记46(多线程三:线程之间的通信)的更多相关文章

  1. Java基础学习笔记: 多线程,线程池,同步锁(Lock,synchronized )(Thread类,ExecutorService ,Future类)(卖火车票案例)

    多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念.进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线 ...

  2. Java多线程编程-线程之间的通信

    转载自:这里 学习了基础的线程知识 看到了 线程之间的通信 线程之间有哪些通信方式呢? 1.同步 这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信. public ...

  3. 20145316许心远《Java学习笔记》第三周总结

    20145316许心远<Java程序设计>第3周学习总结 教材学习内容总结 一.定义类: 类定义时使用class关键字 如果要将x绑定到新建的对象上,可以使用"="制定 ...

  4. 【原】Java学习笔记032 - 多线程

    package cn.temptation; public class Sample01 { public static void main(String[] args) { /* * [进程]:正在 ...

  5. Java学习笔记:多线程(二)

    与线程生命周期相关的方法: sleep 调用sleep方法会进入计时等待状态,等待时间到了,进入就绪状态. yield 调用yield方法会让别的线程执行,但是不确保真正让出.较少使用,官方注释都说 ...

  6. java之等待唤醒机制(线程之间的通信)

    线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同.比如:线程A用来生成包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的动作,一个是生产,一个是消 ...

  7. 10月9日Android学习笔记:活动与服务之间的通信

    最近在照着<第一行代码>这本书来学安卓,顺便记下笔记.主要的内容是Android中服务的第二种启动方式,通过活动绑定服务来启动服务,实现活动与服务之间的通信. 一. 首先创建一个服务类 p ...

  8. Java学习笔记:多线程(一)

    Java中线程的五种状态: 新建状态(New) 就绪状态(Runnable) 运行状态(Running) 阻塞状态(Blocked) 凋亡状态(Dead) 其中阻塞状态(Blocked)又分为三种: ...

  9. Java 学习笔记(11)——多线程

    Java内部提供了针对多线程的支持,线程是CPU执行的最小单位,在多核CPU中使用多线程,能够做到多个任务并行执行,提高效率. 使用多线程的方法 创建Thread类的子类,并重写run方法,在需要启动 ...

随机推荐

  1. tomcat8做成windows服务

  2. typedef typename

    所以根据上述两条分析,  typedef typename RefBase::weakref_type weakref_type; 语句的真是面目是: typedef创建了存在类型的别名,而typen ...

  3. cleos

    [cleos] 1.在.bashrc中加入以下代码,方便直接使用 cleos,7777是nodeos端口,5555是keosd端口. alias cleos='docker exec -it eosi ...

  4. POJ-3268.SilverCowParty.(最短路 + 图的转置)

    本题思路:对原图和原图的逆图分别用一次最短路,找出最大值即可. 一开始是我是对每个顶点spfa搜了一波,结果判题时间巨长,还好这个题的数据量不是很大,所以就用了另一种思路. 参考代码:spfa单结点爆 ...

  5. Unity 2018 By Example 2nd Edition

    Unity is the most exciting and popular engine used for developing games. With its 2018 release, Unit ...

  6. EasyUI datagrid单元格文本超出显示省略号,鼠标移动到单元格显示文本

    nowrap : true;  是前提 $('#×××').datagrid({ nowrap : true,//设置为true,当数据长度超出列宽时将会自动截取 }); 省略号样式: <sty ...

  7. Solidity的三种合约间的调用方式 call、delegatecall 和 callcode

    0x00 前言 Solidity(http://solidity.readthedocs.io/en/v0.4.24/) 是一种用与编写以太坊智能合约的高级语言,语法类似于 JavaScript. S ...

  8. Powershell 脚本判断制定路径下文件是否存在(来源于网络-转载)

    $filelist=gc "file.txt" #获取要检查的文件列表 $csvs= new-object collections.arraylist #创建一个arraylist ...

  9. 通过github安装crawley出现的问题

    http://www.cnblogs.com/hbwxcw/p/7086188.html

  10. 选择困难症的福音——团队Scrum冲刺阶段-Day 4

    选择困难症的福音--团队Scrum冲刺阶段-Day 4 今日进展 编写提问部分 做了不同问题所对应的游戏选项,但关于游戏分类的界面还没有做完 增加功能 昨天在主界面增加"关于我们" ...