多线程-等待唤醒机制

等待唤醒机制


我们希望的效果是,间隔输出的效果


我们应该多定义一个标记boolean flag,判断资源的情况,boolean flag = false,代表里面没有东西,就
可以往里面传,boolean flag = true;此时输入线程仍然具有执行权,这时候就不应该让输入线程继续输入
了,我们希望的效果是,这时候应该输出了,但是输出线程此时并没有执行权。


所以应该让输入线程停一下,停多长时间呢?至少应该等到输出线程执行完毕吧。让输入线程处于冻结状态,


当boolean flag = true;时,代表着资源里有数据
if(flag){//输入
   wait();//资源里有数据的时候,让输入线程冻结,即处于临时堵塞状态
此时输出线程具有了执行权,并输出数据,
将flag变为false,变为false后,输出线程等待


if(!flag){输出
wait();
}


这个时候,两个线程都处于等待的状态,
应该在下一次等待之前,唤醒对应的线程。
if(!flag)//output
	wait();
...//进行输出资源操作
flag = false;//输出结束后,输出线程进入冻结状态
notify();//唤醒输入线程


if(flag){
	wait();
...//进行输入资源操作	
flag = true;//输入结束后,输入线程进入冻结状态
notify();//唤醒输出线程
}
涉及的方法;
1.wait();让线程处于冻结状态,被wait的线程会被存储到线程池中


2.notify();唤醒线程池中的一个线程(任意)


3.notifyAll();唤醒线程池中的所有线程


这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法,必须要明确到底操作的是哪个锁上的线程

class Resource{
	String name;
	String sex;
	boolean flag = false;//在Resource类中,定义一个默认为假的布尔型变量,代表着没有数据
	
}

class Input implements Runnable{
	
	Resource r;
	Input(Resource r){
		this.r = r;
	}
	
	public void run(){
		while(true){
			synchronized(r){
				if(r.flag){
					try{//简单处理一下InterruptedException
						r.wait();
					}
					catch(InterruptedException e){
						
					}
					/*wait、notify是用来监视线程状态的,应该明确wait的是哪个锁上的线程,如果wait的是A锁上的线程,那么notify的
					时候,也应该是A锁上的线程。所以应该标识出锁。
					*/

				}
				if(x == 0){
					name = "mike";
					sex = "man";
				}
				else{
					name = "丽丽";
					sex = "女"
				}
				r.flag = true;
				r.notify();//如果对方没等待的时候,可不可以唤醒呢?可以的,可以存在一次空唤醒。
			}

			x = (x + 1)%2;
		}
	}
}

clss Output implements Runnable{
	
	Resource r;
	Output(Resource r){
		this.r = r;
	}
	
	public void run(){
		while(true){
			synchronized(r){
				if(!r.flag){
					try{//简单处理一下InterruptedException
						r.wait();
					}
					catch(InterruptedException e){
						
					}
				}
				System.out.println(r.name + "..." +r.sex);
				r.flag = false;
				r.notify();
			}
		}
	}
	
}

class Test{
	public static void main(String [] args){
		Resource r = new Resource();
		
		Input in = new Input(r);
		Output out = new Output(r);
		
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		
		t1.start();
		t2.start();
	}
}
查看API发现,wait()不是Thread中的方法,而是定义在了Object类中了。为什么?
因为这些方法是监视器方法,监视器其实就是锁。锁可以是任意的对象,任意的对象调用的方法,一定定义在了Object中。


如果你被r.wait()了,那么就被存到了r的线程池(等待集)了。操作锁,其实是操作锁上线程的方法。


编译会报告java.lang.InterruptedException异常,这是正常的。
因为:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值