生产者和消费者问题
在操作系统的课程中,生产者和消费者问题涉及PV操作(wait操作和signal操作),生产者消费者问题通俗的讲就是,当生产者生产的时候,消费者不能消费,消费者消费的时候,生产者不能生产,两者存在互斥访问缓冲区(放产品和取出产品的地方空间叫做缓冲区).
举例来说
现在有一个生产者在生产包子,一次生产一个,放入缓冲区,有一个消费者,一次买走一个包子,从缓冲区取走一个,现在缓冲区包子数量为0时,消费者就等待,生产者就生产包子,生产者生产了一个包子后,缓冲区包子数量就为1了,此时生产者阻塞,等待消费者消费.
代码演示:
Student的类(包子筐)
package com.westos.morning1;
class Student{
public static String name;
public static int age;
public static boolean flag;//默认是false 代表没有资源,true 代表有资源
}
Set子线程(生产包子)
package com.westos.morning1;
public class SetThread extends Thread{
Student student;
public SetThread(Student student) {
this.student=student;
}
@Override
public void run() {
int i=0;
for (int j = 0; j < 100; j++) {
synchronized (student){
if(student.flag){
try {
student.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(i%2==0) {
student.name = "张三";
student.age = 33;
}else {
student.name = "李四";
student.age = 44;
}
i++;
student.flag=true;
student.notify();//唤醒被阻塞的进程
}
}
}
}
Get子线程(消费包子)
package com.westos.morning1;
public class GetThread extends Thread {
Student student;
public GetThread(Student student) {
this.student = student;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
synchronized (student) {
if (student.flag) {
System.out.println(student.name + "===" + student.age);
student.flag = false;
student.notify();//唤醒被阻塞的
}
try {
student.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
主线程
package com.westos.morning1;
public class Demo {
public static void main(String[] args) {
Student student = new Student();
SetThread setThread = new SetThread(student);
GetThread getThread = new GetThread(student);
getThread.start();
setThread.start();
}
}
均匀运行,一个阻塞,一个被唤醒,一个被唤醒,另一个又阻塞,来回交替.
补充:
Object类中
wait()方法,使当前线程等待,一旦等待,就立马释放锁.下次被唤醒之后,从哪里等待的,就从哪里又开始执行
notify()方法,唤醒在此时监视器上等待的单个线程,被唤醒后,还得再次争抢时间片,不一定执行.
sleep()和wait()区别:
两个都能让线程处于阻塞状态.
sleep()必须传入时间量.
wait()可以传入时间量,也可以不传入.
sleep()线程休眠后,不释放锁.
wait()一旦等待,就立即释放锁.
谢谢!