介绍
多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。通过等待唤醒机制可以使各个线程能有效的利用资源。
等待唤醒机制所涉及到的方法:
wait():等待,将正在执行的线程释放其执行资格和执行权,并存储到线程池中。
notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。
notifyAll():唤醒全部,可以将线程池中的所有wait()线程都唤醒。
实现
利用锁和等待唤醒机制实现生产一次消费一次。
public class Person {
String name;
String sex;
/**
* @Fields flag : 定义布尔值,作为判断哪个线程等待的标记位:true有数据,生产者等待;false无数据,消费者等待;
*/
boolean flag;
public Person() {
super();
}
}
public class PutIn implements Runnable{
//内部共享变量
private Person person;
//通过构造方法,从外界接收共享的那个资源
public PutIn(Person person){
this.person=person;
}
@Override
public void run() {
//使用死循环达到反复生成的目的
//如果是奇数,生成Jame 男;如果是偶数,生成Rose 女;
int i=0;
while(true){
//使用共享对象作为锁
synchronized(person){
//判断标志位
while(person.flag){
//如果有数据,就等待
try {
person.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有数据或者刚刚被唤醒
//判断生产内容
if(i%2==1){
person.name="Jame";
//线程睡眠100毫秒
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
person.sex="男";
}else{
person.name="Rose";
//线程睡眠100毫秒
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
person.sex="女";
}
System.out.println(person);
System.out.println("生产了:"+person.name+"-"+person.sex);
//该标记位为true
person.flag=true;
//如果有消费者等待,就唤醒消费者;如果没有就无需唤醒,相当于这句代码没有执行
person.notify();
}
//每次生成完,更改奇偶对应的整数
i++;
}
}
}
public class GetOut implements Runnable{
//内部共享变量
private Person person;
//通过构造方法,从外界接收共享的那个资源
public GetOut(Person person){
this.person=person;
}
@Override
public void run() {
//使用死循环达到反复生成的目的
while(true){
//使用共享对象作为锁
synchronized(person){
//判断标记位
while(!person.flag){
//如果没有数据,就等待
try {
person.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果有数据或者刚刚被唤醒
//线程睡眠100毫秒
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = person.name;
String sex= person.sex;
System.out.println(person);
System.out.println("消费了:"+name+"-"+sex);
//该标记位为false
person.flag=false;
//如果有生产者等待,就唤醒生产者;如果没有就无需唤醒,相当于这句代码没有执行
person.notify();
}
}
}
}
public class WaitNotifyDemo {
public static void main(String[] args) {
//共享资源
Person person = new Person();
//创建生产者线程执行目标
PutIn putIn = new PutIn(person);
//创建消费者线程执行目标
GetOut getOut = new GetOut(person);
//开启生产者线程
Thread putInThread = new Thread(putIn);
putInThread.start();
//开启消费者线程
Thread getOutThread = new Thread(getOut);
getOutThread.start();
}
}