生产者消费者模式
1,生产者只在仓库未满时进行生产,仓库满时生产者进程被阻塞。
2,消费之只在仓库非空时进行消费,仓库为空时消费者进程被阻塞。
生产者消费者问题都是通过锁的竞争进行资源的消耗或生产。
方法一:synchronized,wait,notify
资源
public class Resource { //当前资源的数量 int number = 0; //当前资源的上限 int size = 10; //控制执行的标识 boolean flag = true; //生产资源 public synchronized void produce() { //如果资源满了,就进入阻塞状态 //jdk里推荐用while,因为有可能出现虚假唤醒,所以再次确认 while (number == size) { try { System.out.println(Thread.currentThread().getName() + "\t" + "进入等待"); //线程进入阻塞状态,并释放锁 this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } number++; System.out.println(Thread.currentThread().getName() + "\t" + "生产资源" + number); //唤醒其他正在等待的线程 this.notify(); } //消费资源 public synchronized void consume() { //如果num为0,没有资源了,需要等待 //这里jdk源码里推荐用while,因为有可能虚假唤醒,所以要再次确认 while (number == 0) { try { System.out.println(Thread.currentThread().getName() + "\t" + "进入等待"); //线程等待,并释放锁 this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "\t" + "消费资源" + number); number--; //唤醒其他正在等待的线程 this.notify(); } //停止执行 public void stop() { this.flag = false; } }
生产者
public class Producer implements Runnable { private Resource resource; public Producer(Resource resource){ this.resource=resource; } @Override public void run() { while (resource.flag){ resource.produce(); } System.out.println(Thread.currentThread().getName()+"\t"+"生产者停止线程"); } }
消费者
public class Consumer implements Runnable { private Resource resource; public Consumer(Resource resource){ this.resource=resource; } @Override public void run() { while (resource.flag){ resource.consume(); } System.out.println(Thread.currentThread().getName()+"\t"+"消费者停止线程"); } }
测试代码
public class TestProducerAndConsumer { public static void main(String[] args) { Resource resource = new Resource(); Thread producer=new Thread(new Producer(resource),"producer"); Thread consumer=new Thread(new Consumer(resource),"consumer"); producer.start(); consumer.start(); try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("停止线程"); resource.flag=false; } }
方法二:lock,condition,await,singal
资源
public class Resource { //当前资源的数量 int number = 0; //当前资源的上限 int size = 10; //控制执行的标识 boolean flag = true; //创建所对象 Lock lock = new ReentrantLock(); //创建锁的条件、情况 Condition condition = lock.newCondition(); //生产资源 public void produce() { //开启锁 lock.lock(); try { //当资源满时,需要等待 //jdk源码里推荐使用while,因为有可能出现虚假唤醒,所以再次确认 while (number == size) { System.out.println(Thread.currentThread().getName() + "\t" + "进入等待"); try { //线程等待,释放锁 condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } number++; System.out.println(Thread.currentThread().getName() + "\t" + "生产资源" + number); //唤醒其他线程 condition.signal(); } finally { lock.unlock(); } } //消费资源 public void consume() { //开启锁 lock.lock(); try { //如果number为0,没有资源了,需要等待 //jdk源码里推荐使用while,因为有可能出现虚假唤醒,所以再次确认 while (number == 0) { System.out.println(Thread.currentThread().getName() + "\t" + "进入等待"); try { //线程等待,释放锁 condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "\t" + "消费资源" + number); number--; //唤醒其他线程 condition.signal(); } finally { //释放锁 lock.unlock(); } } public void stop() { this.flag = false; } }
生产者、消费者和测试代码都和上面一样。
方法三:BlockingQueue
资源
public class Resource { AtomicInteger atomicInteger=new AtomicInteger(); boolean flag=true; BlockingQueue blockingQueue=null; public Resource(BlockingQueue blockingQueue){ this.blockingQueue=blockingQueue; } public void produce(){ try { int number = atomicInteger.incrementAndGet(); boolean result = blockingQueue.offer(number, 2L, TimeUnit.SECONDS); if(result){ System.out.println(Thread.currentThread().getName()+"\t"+"生产资源成功"+number); }else{ System.out.println(Thread.currentThread().getName()+"\t"+"生产资源失败"+number); } TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } public void consume(){ try { Integer number =(Integer) blockingQueue.poll(2L, TimeUnit.SECONDS); if(number==null){ flag=false; System.out.println(Thread.currentThread().getName()+"\t"+"超过2秒钟消费资源,线程停止"); return; } System.out.println(Thread.currentThread().getName()+"\t"+"消费资源"+number); //atomicInteger.getAndDecrement(); } catch (InterruptedException e) { e.printStackTrace(); } } public void stop(){ this.flag=false; } }
生产者
public class Producer implements Runnable { Resource resource=null; public Producer(Resource resource){ this.resource=resource; } @Override public void run() { while (resource.flag){ resource.produce(); } System.out.println(Thread.currentThread().getName()+"\t"+"生产线程停止了"); } }
消费者
public class Consumer implements Runnable { Resource resource=null; public Consumer(Resource resource){ this.resource=resource; } @Override public void run() { while (resource.flag){ resource.consume(); } System.out.println(Thread.currentThread().getName()+"\t"+"消费线程停止了"); } }
测试代码
public class TestProducerAndConsumer { public static void main(String[] args) { BlockingQueue<Integer> blockingQueue=new ArrayBlockingQueue<>(10); Resource resource=new Resource(blockingQueue); Thread producer = new Thread(new Producer(resource), "producer"); Thread consumer = new Thread(new Consumer(resource), "consumer"); producer.start(); consumer.start(); try { TimeUnit.SECONDS.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("停止线程"); resource.flag=false; } }
posted on
浙公网安备 33010602011771号