使用Java BlockingQueue实现的生产者和消费者
1.定义生产者
class Producer implements Runnable {
private BlockingQueue<String> queue;
private String id;
private volatile boolean isRunning = true;
private static AtomicInteger count = new AtomicInteger();
public Producer(BlockingQueue<String> queue, String id) {
this.queue = queue;
this.id = id;
}
public void stop() {
isRunning = false;
}
@Override
public void run() {
String data = null;
try {
while (isRunning) {
System.out.println("PRODUCER: " + id + " is running");
Thread.sleep(100);
data = "data:" + count.incrementAndGet();
System.out.println("Thread: " + id + " procedued data into queue: " + data + " ...");
if (!queue.offer(data, 2, TimeUnit.SECONDS)) {
System.out.println("failed to put data into queue: " + data);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
} finally {
System.out.println("Thread: " + id + " quit from producer thread");
}
}
}
2.定义消费者
class Consumer implements Runnable {
/**
* 用util.concurrent.BlockingQueue沟通生产者和消费者的桥梁
*/
private BlockingQueue<String> queue;
private String id;
private volatile boolean isRunning = true;
public Consumer(BlockingQueue<String> queue, String id) {
this.queue = queue;
this.id = id;
}
public void stop() {
isRunning = false;
}
@Override
public void run() {
System.out.println("Thread: " + id + " Consumer thread is running...");
boolean isRunning = true;
try {
while (isRunning) {
System.out.println("Thread: " + id + " fetch data from linkedQueue..." + " queue size: " + queue.size());
/*
* 从队列里取出一个元素,2秒超时,如果两秒之后还没有东西可以取,则poll返回null
*/
String data = queue.poll(2, TimeUnit.SECONDS);
if (null != data) {
System.out.println("Thread: " + id + " has consumed one data from queue: " + data
+ " Queue sise: " + queue.size());
// simulate data consumption
Thread.sleep(1000);
} else {
isRunning = false;
// 消费者准备退出
System.out.println("Thread: " + id + " Consumer read queue timeout");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
} finally {
System.out.println("Thread: " + id + " consumer thread ends");
}
}
}
3,测试
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class TaskProductFactory {
public static void main(String args[]) throws InterruptedException {
BlockingQueue<String> queue = new LinkedBlockingQueue<>(15);
Producer producer1 = new Producer(queue, "PROD1");
Producer producer2 = new Producer(queue, "PROD2");
Producer producer3 = new Producer(queue, "PROD3");
Consumer consumer1 = new Consumer(queue, "CONSUMER1");
Consumer consumer2 = new Consumer(queue, "CONSUMER2");
java.util.concurrent.ExecutorService service = Executors.newCachedThreadPool();
service.execute(producer1);
service.execute(producer2);
service.execute(producer3);
service.execute(consumer1);
service.execute(consumer2);
Thread.sleep(3 * 1000);
producer1.stop(); // 一定要先关闭生产者
producer2.stop();
producer3.stop();
consumer1.stop();
consumer2.stop();
Thread.sleep(2000);
service.shutdown();
}
}
Thread: CONSUMER1 has consumed one data from queue: data:19 Queue sise: 5
Thread: CONSUMER2 has consumed one data from queue: data:20 Queue sise: 4
Thread: CONSUMER1 fetch data from linkedQueue... queue size: 4
Thread: CONSUMER2 fetch data from linkedQueue... queue size: 4
Thread: CONSUMER2 has consumed one data from queue: data:22 Queue sise: 2
Thread: CONSUMER1 has consumed one data from queue: data:21 Queue sise: 2
Thread: CONSUMER1 fetch data from linkedQueue... queue size: 2
Thread: CONSUMER2 fetch data from linkedQueue... queue size: 2
Thread: CONSUMER1 has consumed one data from queue: data:24 Queue sise: 1
Thread: CONSUMER2 has consumed one data from queue: data:23 Queue sise: 0
Thread: CONSUMER1 fetch data from linkedQueue... queue size: 0
Thread: CONSUMER2 fetch data from linkedQueue... queue size: 0
Thread: CONSUMER1 Consumer read queue timeout
Thread: CONSUMER2 Consumer read queue timeout
Thread: CONSUMER2 consumer thread ends
Thread: CONSUMER1 consumer thread ends
可以把公共资源抽取出来
import lombok.SneakyThrows;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
//公共资源
public class ShareResource {
private BlockingQueue<String> queue;
private int capacity = 0;
public ShareResource(int capacity) {
this.capacity = capacity;
queue = new LinkedBlockingQueue<>(capacity);
}
// 生产产品
@SneakyThrows
public void produce() {
// 生产条件满足情况下,生产产品
Random random = new Random();
int i = random.nextInt();
System.out.println("线程(" + Thread.currentThread().getName() + ")生产了一件产品: " + i + ";当前剩余商品" + queue.size() + "个");
queue.add(String.valueOf(i));
}
// 消费产品
@SneakyThrows
public void consume() {
String product = queue.take();
System.out.println("线程(" + Thread.currentThread().getName() + ")消费了一件产品:" + product + ";当前剩余商品" + queue.size() + "个");
}
}
class Producer implements Runnable {
private ShareResource shareResource;
public Producer(ShareResource shareResource) {
this.shareResource = shareResource;
}
@Override
public void run() {
try {
while (true) {
shareResource.produce();
Thread.sleep(500);
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
/**
* 消费者
*/
class Consumer implements Runnable {
private ShareResource shareResource;
public Consumer(ShareResource shareResource) {
this.shareResource = shareResource;
}
@Override
public void run() {
while (true) {
shareResource.consume();
}
}
public static void main(String[] args) {
java.util.concurrent.ExecutorService service = Executors.newCachedThreadPool();
ShareResource shareResource = new ShareResource(5);
Producer producer1 = new Producer(shareResource);
Producer producer2 = new Producer(shareResource);
Consumer consumer1 = new Consumer(shareResource);
Consumer consumer2 = new Consumer(shareResource);
Consumer consumer3 = new Consumer(shareResource);
service.execute(producer1);
service.execute(producer2);
service.execute(consumer1);
service.execute(consumer2);
service.execute(consumer3);
}
}