生产者消费者问题是老生常谈的问题,考察线程的同步等知识
Java中用于实现生产者消费者主要使用synchronized、对象.wait()、对象.notify()来实现
前置知识
synchronized
该字段可对方法使用、可对代码片使用,用于控制线程互斥
wait()
用于通知掌握该对象锁的线程等待通知
notify()
用于通知等待对象锁的线程开始运行
生产者消费者
其中list是生产者消费者共享的资源
每次该共享资源被释放(生产完或消费完),生产者消费者都有可能进入临界区,但无所谓,不满足条件的会卡住,让另一个执行
public class ProduceConsume {public static void main(String[] args) {List list =new ArrayList();Producer p=new Producer(list);Consumer c=new Consumer(list);new Thread(p,"生产者").start();new Thread(c,"消费者").start();}
}class Producer implements Runnable {private List list;public Producer(List list) {this.list = list;}public void run(){while(true){synchronized (list) {//synchronized控制不同线程同步if (list.size()>0){//如果发现不能生产 就调用wait(),释放锁try {list.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}else{//否则就生产一个,并通知消费者可以来拿//就算下次又是生产者进来,那无所谓,会进入waitproduce();list.notifyAll();}}}}public void produce(){list.add(new Object());//加到后面System.out.println(Thread.currentThread().getName()+"生产产品");}
}
class Consumer implements Runnable {private List list;public Consumer(List list) {this.list = list;}public void run(){while (true){synchronized (list) {if (list.size()==0){try {list.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}else{consume();list.notifyAll();}}}}public void consume(){list.remove(0);System.out.println(Thread.currentThread().getName()+"消费产品");}
}
三个线程交替打印数字
这里思想非常简单,在生产者消费者的基础上,有以下变化:
- 共享资源变成三个,两两使用一个控制同步
- 每个线程消费后再生产,这样下一个线程可以消费再生产
- 两层synchronized嵌套,第一层控制消费,第二层控制生产
- main函数里初始化往第一个共享资源生产一下,使得整体开始运行
- 三个线程共享代码段,只是传入的参数不同
import java.util.ArrayList;
import java.util.List;public class PrintInTurn {public static void main(String[] args) {List list1 = new ArrayList();List list2 = new ArrayList();List list3 = new ArrayList();list1.add(new Object());ProducerConsumer p1=new ProducerConsumer(list1,list2);ProducerConsumer p2=new ProducerConsumer(list2,list3);ProducerConsumer p3=new ProducerConsumer(list3,list1);new Thread(p1,"p1").start();new Thread(p2,"p2").start();new Thread(p3,"p3").start();}
}class ProducerConsumer implements Runnable {private List list1,list2;public ProducerConsumer(List list1, List list2) {this.list1 = list1;this.list2 = list2;}public void run(){//int i=0;//控制生产个数while(true){//if (i>2){//控制生产个数// break;//}synchronized (list1) {if (list1.size()==0){//线程进入等待try {list1.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}else{consume(list1);//i++;//控制生产个数list1.notifyAll();synchronized (list2) {if (list2.size()==1){try {list2.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}else{produce(list2);list2.notifyAll();}}}}}}public void produce(List lis){lis.add(new Object());//加到后面System.out.println(Thread.currentThread().getName()+"生产产品");}public void consume(List lis){lis.remove(0);
// System.out.println(Thread.currentThread().getName()+"消费产品");}
}