生产者和消费者问题的描述图
通过上图,我们可以发现:
生产者和消费者使用的都是同一个资源(肉包子)
所以,当使用线程的时候,这两类的锁也是同一把锁(为了避免出现线程安全问题)
例子:学生信息的录入和获取
* 资源类:Student
* 设置学生数据:SetThread(生产者)
* 获取学生数据:GetThread(消费者)
* 测试类:StudentDemo
* 资源类:Student
1 public class Student { 2 3 String name; 4 int age; 5 }
* 设置学生数据:SetThread(生产者)
public class SetThread implements Runnable { private int x = 0; // 因为SetThread和Getthread两个类使用的都是同一个资源 // 所以,在创建一个资源对象,再通过构造方法传递给其它的类 private Student s; public SetThread(Student s) { this.s = s; } public void run() { // 录入信息(生产者) while (true) { // 加锁,且SetThread和Getthread两个类使用的是同一把锁,所以锁的对象是资源对象s synchronized (s) { if (x % 2 == 0) { s.name = "张三"; s.age = 23; } else { s.name = "李四"; s.age = 24; } x++; } } } }
* 获取学生数据:GetThread(消费者)
1 public class GetThread implements Runnable { 2 3 private Student s; 4 public GetThread(Student s){ 5 this.s = s; 6 } 7 public void run() { 8 //获取信息 消费者 9 //锁的对象,同SetThread 10 while(true){ 11 synchronized (s){ 12 System.out.println(s.name +"--" + s.age); 13 } 14 } 15 16 } 17 18 }
* 测试类:StudentDemo
1 public class StudentDemo { 2 3 4 public static void main(String[] args) { 5 6 //创建资源对象 7 Student s = new Student(); 8 9 //创建录入和获取类的对象 10 SetThread st = new SetThread(s); 11 GetThread gt = new GetThread(s); 12 13 //创建线程对象 14 Thread t1 = new Thread(st); 15 Thread t2 = new Thread(gt); 16 17 //启动线程 18 t1.start(); 19 t2.start(); 20 21 } 22 23 }
结果:
生产者SetThread类不断地录入学生信息(可以看成不断生产包子?)
而消费者GetThread类则不断地获取所录入的信息(买包子?)
当然,最理想的状态是生产者生产1个,消费者就立马消费1个....
但,这里还不是这种理想状态,两者还是得抢占CPU的资源,若是生产的多,则就堆积着等消费者。
若是消费者抢占的资源多,则一直消费的都是同一个包子?。。