博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java多线程-52-三个和三个以上线程之间的通信
阅读量:4302 次
发布时间:2019-05-27

本文共 4143 字,大约阅读时间需要 13 分钟。

        前面一篇介绍了两个线程之间的通信,那么三个线程和三个以上线程之间的通信是如何实现呢。我们前面一篇在查询Object类的时候,知道有一个wait()和notify()方法,同时还有一个notifyAll()方法。这个notfiyAll()方法就是来解决三个以上线程通信的。

1.基于前面知识,添加一个线程,看看执行效果

package thread;public class NotifyAll_Demo {	public static void main(String[] args) {		Printer2 p = new Printer2();		new Thread() {			public void run() {				while(true) {					try {						p.print1();					} catch (InterruptedException e) {						e.printStackTrace();					}				}			}		}.start();				new Thread() {			public void run() {				while(true) {					try {						p.print2();					} catch (InterruptedException e) {						e.printStackTrace();					}				}			}		}.start();				new Thread() {			public void run() {				while(true) {					try {						p.print3();					} catch (InterruptedException e) {						e.printStackTrace();					}				}			}		}.start();	}}class Printer2 {	private int flag = 1;	public void print1() throws InterruptedException {		synchronized (this) {			if(flag != 1) {				this.wait();  // 设置线程等待,如果flag 不等于1			}			System.out.print("跟");			System.out.print("我");			System.out.print("一");			System.out.print("起");			System.out.println("念");			flag = 2;			this.notify(); // 设置flag等于2,使用线程唤醒功能,其他线程就可以启动		}	}		public void print2() throws InterruptedException {		synchronized (this) {			if(flag != 2) {				this.wait();  // 设置线程等待,如果flag 不等于2			}			System.out.print("做");			System.out.print("测");			System.out.print("试");			System.out.print("死");			System.out.print("路");			System.out.print("一");			System.out.println("条");			flag = 3;			this.notify();  //随机唤醒单个等待的线程		}	}		public void print3() throws InterruptedException {		synchronized (this) {			if(flag != 3) {				this.wait();  // 设置线程等待,如果flag 不等于2			}			System.out.print("信");			System.out.print("才");			System.out.print("怪");			System.out.println("呢");			flag = 1;			this.notify();  //随机唤醒单个等待的线程		}	}}

运行效果:

做测试死路一条跟我一起念信才怪呢做测试死路一条跟我一起念信才怪呢做测试死路一条跟我一起念信才怪呢做测试死路一条跟我一起念信才怪呢做测试死路一条跟我一起念

发现打印顺序有问题,主要有两个原因,if语句有一个特点,代码在哪里停止(上面wait)就在哪里起来。第二个特点就是notify()是随机唤醒等待线程。这个随机特点就造成了打印结果顺序不可控。

2.if语句换成while语句,notify()方法换成notifyAll()方法

if没有每次都对flag进行判断,但是while语句会每次都进行条件判断。notifyAll()就是把全部的线程都唤醒,然后这些线程去判断,再执行相关打印。

package thread;public class NotifyAll_Demo {	public static void main(String[] args) {		Printer2 p = new Printer2();		new Thread() {			public void run() {				while(true) {					try {						p.print1();					} catch (InterruptedException e) {						e.printStackTrace();					}				}			}		}.start();				new Thread() {			public void run() {				while(true) {					try {						p.print2();					} catch (InterruptedException e) {						e.printStackTrace();					}				}			}		}.start();				new Thread() {			public void run() {				while(true) {					try {						p.print3();					} catch (InterruptedException e) {						e.printStackTrace();					}				}			}		}.start();	}}class Printer2 {	private int flag = 1;	public void print1() throws InterruptedException {		synchronized (this) {			while(flag != 1) {				this.wait();  // 设置线程等待,如果flag 不等于1			}			System.out.print("跟");			System.out.print("我");			System.out.print("一");			System.out.print("起");			System.out.println("念");			flag = 2;			this.notifyAll(); 		}	}		public void print2() throws InterruptedException {		synchronized (this) {			while(flag != 2) {				this.wait();  // 设置线程等待,如果flag 不等于2			}			System.out.print("做");			System.out.print("测");			System.out.print("试");			System.out.print("死");			System.out.print("路");			System.out.print("一");			System.out.println("条");			flag = 3;			this.notifyAll();  		}	}		public void print3() throws InterruptedException {		synchronized (this) {			while(flag != 3) {				this.wait();  // 设置线程等待,如果flag 不等于2			}			System.out.print("信");			System.out.print("才");			System.out.print("怪");			System.out.println("呢");			flag = 1;			this.notifyAll();  		}	}}

运行效果:

跟我一起念做测试死路一条信才怪呢跟我一起念做测试死路一条信才怪呢跟我一起念做测试死路一条信才怪呢跟我一起念做测试死路一条信才怪呢跟我一起念做测试死路一条信才怪呢...

 

多线程之间需要注意的问题

1.在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法(例如上面的this)

2.为什么wait方法和notify方法定义在Object这个类中
   因为锁对象可以是任意对象,Object是所有类的基类,所以wait方法和notify方法需要定义在Object类中

3.sleep方法和wait方法的区别

第一个区别:sleep方法必须传入参数,参数就是时间,时间到了自动醒来。wait方法可以传入参数也可以不传入参数,传入参数就是在参数时间结束后等待,不传入参数就是直接等待。
第二个区别:sleep方法在同步函数或者同步代码块中,不释放锁。wait方法在同步函数或者同步代码块中,释放锁。
 

转载地址:http://nzows.baihongyu.com/

你可能感兴趣的文章
DataWhale计算机视觉实践(目标检测)Task02
查看>>
DataWhale计算机视觉实践(目标检测)Task03
查看>>
DataWhale计算机视觉实践(目标检测)Task04
查看>>
LeetCode 刷题记录26. 删除有序数组中的重复项
查看>>
GlusterFS 3.4.2 安装记录
查看>>
Linux C/C++编程一站式学习中输出菱形
查看>>
glusterfs 3.4.2安装记录(一)
查看>>
Linux C/C++编程一站式学习--以可视化的形式打印直方图
查看>>
Linux C/C++编程一站式学习中选择排序
查看>>
Linux C/C++编程一站式学习中折半查找(如果待查找的元素在数组中有多个则返回第一个)
查看>>
Git分布式版本控制系统笔记
查看>>
Codewars第二天--Complementary DNA
查看>>
Codewars第二天--Disemvowel Trolls
查看>>
Codewars第三天--Binary Addition
查看>>
Codewars第三天--The museum of incredible dull things
查看>>
Codewars第四天--Find the stray number
查看>>
Codewars第三天--Unique In Order
查看>>
Codewars第三天--Largest 5 digit number in a series
查看>>
Codewars第三天--Breaking chocolate problem
查看>>
Codewars第三天--Create Phone Number
查看>>