Java多线程-52-三个和三个以上线程之间的通信

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011541946/article/details/85869191

        前面一篇介绍了两个线程之间的通信,那么三个线程和三个以上线程之间的通信是如何实现呢。我们前面一篇在查询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方法在同步函数或者同步代码块中,释放锁。
 

猜你喜欢

转载自blog.csdn.net/u011541946/article/details/85869191