java 多线程的生产者-消费者 实现
程序员文章站
2022-04-23 08:36:33
...
Java 语言实现生产者 -- 消费者模式,本文采用1个生产者和3个消费者,以体现多线程并发过程中应该注意的地方。
其中,容器采用java.util.concurrent.LinkedBlockingQueue,这是一个并发容器,包concurrent就是Java专门为实现并发而提供的一组工具包。
思路:一个容量为100的容器,一个生产者(一个线程)不断向其中添加从0开始的整数,如果超出容器范围则线程阻塞1s,与此同时,三个消费者(三个线程,当然也可以是更多~)不断向容器拿出整数,如果容器取空,则线程阻塞1s。
对容器操作是主要的部分,此处要考虑线程的并发性,而此时因为LinkedBlockingQueue是线程安全的,因此就可以不用加锁和Syncholized关键字等。多方便啊~
public class BlockingQueueTest { private BlockingQueue<Integer> bq; private int M=100; public BlockingQueueTest() { bq = new LinkedBlockingQueue<>(M); } public boolean putIn(int n) { if(bq.size()<M) { bq.add(n); return true; }else{ return false; } } public int getOut() { if(bq.size()>0) { return bq.poll(); }else{ return -1; } } }
容器实现了,就实现生产者和消费者这两个线程吧,线程的实现主要有两种:一种是继承父类Thread,第二种是实现接口Runnable();此处实现接口—>减少类之间的耦合度。
public void run() { while (true) { for (int i=0; i<100000;i++) { if (bqt.putIn(i)) { dataOut(Thread.currentThread().getName()+" put:"+i); } else { dataOut("Queue is full ! Sleep for 1s"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
消费者则更加简单:
public void run() { while (true) { int i = bqt.getOut(); if(i!=-1) { dataOut(Thread.currentThread().getName() + " get " + i); }else{ dataOut(Thread.currentThread().getName() +": Queue is empty! Sleep for 1s"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
其中输出的方法实现:(此处可根据具体情况改变)
public void dataOut(String s) { System.out.println(s); }
主要的几个都实现了,生成测试类:
public static void main(String[] args) throws Exception { BlockingQueueTest bqt = new BlockingQueueTest(); Thread f = new Thread(new Productor(bqt)); Thread a = new Thread(new Consumer(bqt)); Thread a1 = new Thread(new Consumer(bqt)); Thread a2 = new Thread(new Consumer(bqt)); f.setName("Productor"); a.setName("consumer 1"); a1.setName("consumer 2"); a2.setName("consumer 3"); f.start(); a.start(); a1.start(); a2.start(); }
最后贴个结果图把: