等待唤醒机制
我们希望的效果是,间隔输出的效果
我们应该多定义一个标记boolean flag,判断资源的情况,boolean flag = false,代表里面没有东西,就
可以往里面传,boolean flag = true;此时输入线程仍然具有执行权,这时候就不应该让输入线程继续输入
了,我们希望的效果是,这时候应该输出了,但是输出线程此时并没有执行权。
所以应该让输入线程停一下,停多长时间呢?至少应该等到输出线程执行完毕吧。让输入线程处于冻结状态,
当boolean flag = true;时,代表着资源里有数据
if(flag){//输入
wait();//资源里有数据的时候,让输入线程冻结,即处于临时堵塞状态
此时输出线程具有了执行权,并输出数据,
将flag变为false,变为false后,输出线程等待
if(!flag){输出
wait();
}
这个时候,两个线程都处于等待的状态,
应该在下一次等待之前,唤醒对应的线程。
1.wait();让线程处于冻结状态,被wait的线程会被存储到线程池中
2.notify();唤醒线程池中的一个线程(任意)
3.notifyAll();唤醒线程池中的所有线程
因为这些方法是监视器方法,监视器其实就是锁。锁可以是任意的对象,任意的对象调用的方法,一定定义在了Object中。
如果你被r.wait()了,那么就被存到了r的线程池(等待集)了。操作锁,其实是操作锁上线程的方法。
编译会报告java.lang.InterruptedException异常,这是正常的。
因为:
我们希望的效果是,间隔输出的效果
我们应该多定义一个标记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异常,这是正常的。
因为: