简介
什么叫做等待唤醒机制呢?举一个栗子,请看下图:
当我们开启两条线程时,一条线程专门输入数据,另条取数据。并且要实现,输入一个数据过后,另一方取出一个数据。在多线程的情况下,当输入线程抢到CPU的执行权后,下一次还有可能是输入线程抢到CPU的执行权,就达不到我们想过要的效果。因此,我们需要输入线程执行一次过后,就让它等待,并叫醒输出线程。然后让输出线程执行,执行一次后等待,并且叫醒输入线程。就这样循环往复,就达到了我们想要的效果。
实现步骤
1.创建User类
package Syn;
public class User {
private String name;
private String sex;
private boolean fig;//用来切换线程
public User() { }
public boolean getFig() { return fig; }
public void set(String name ,String sex){
this.name=name;
this.sex=sex;
}
public String get(){
return this.name+" : "+this.sex;
}
public void setFig(boolean fig) { this.fig = fig; }
}
这个类帮助我们模拟实现数据的输入输出
2.创建一个输入线程Input类
package Syn;
/**
* 线程共享数据问题
*/
public class Input implements Runnable{
private User user;
public Input() { }
public Input(User user) {//传入User对象
this.user = user;
}
@Override
public void run() {
int i=0;
while (true) {
synchronized (user) {
if(user.getFig()) { //如果已经输入数据 让线程等待
try {user.wait();} catch (InterruptedException e) { }
}//为true就让线程等待
if (i == 0) { //每次切换一下 添加不同的数据 方便观察
user.set("Rous","woman");
} else {
user.set("杰克","男");
}
user.setFig(true);//改为true让输输入线程可以执行 输入线程等待
user.notify();//唤醒下一个线程
i = (i + 1) % 2;//切换
}
}
}
}
这一步是等待唤醒机制的核心部分。输入线程第一次进来时fig为false,继续往下执行。set过后,将fig改为true,并且唤醒下一个线程(输出线程)。就算下一次输入线程又抢到了CPU的执行权,判断fig为true则等待。
3.创建一个输出线程Output类
package Syn;
public class Output implements Runnable {
private User user;
public Output() { }
public Output(User user) {
this.user = user;
}
@Override
public void run() {
while (true) {
synchronized (user) {
if(!user.getFig()) { try { user.wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
System.out.println(user.get());
user.setFig(false);
user.notify();
}
}
}
}
假如输出线程第一次抢到CPU的执行权,判断fig为false(User对象默认值为false),等待。当输入线程执行一遍后,就会将fig改为true并且唤醒输出线程,此时输出线程才具备执行资格。输出线程执行一遍后,将fig置为false,并唤醒输入线程,以此往复。
4.创建一个测试类
package Syn;
public class Text {
public static void main(String[] args) {
User user=new User();
new Thread(new Input(user)).start();
new Thread(new Output(user)).start();
}
}
运行结果:
可以看见输入输出线程是来回切换的。
每日鸡汤:但行好事,莫问前程!
Over!