JAVA利用阻塞队列实现生产者消费者模式
思路
- 需要一个
ServiceData
类代表业务数据 - 需要一个
DataProducer
类代表生产者去生产业务数据 - 需要一个
DataConsumer
类代表消费者去消费/处理业务数据 - 需要一个线程池去管理生产者消费者线程
业务数据
/**
* 业务数据
*/
public class ServiceData {
// TODO: setter/getter省略
//业务数据属性
}
生产者代码
import java.util.concurrent.*;
/**
* 生产者
*/
public class DataProducer implements Runnable {
private BlockingQueue<ServiceData> queue;
public DataProducer(BlockingQueue<ServiceData> queue) {
this.queue = queue;
}
@Override
public void run() {
//模拟生产十万个数据
for (int i = 0; i < 100000; i++) {
try {
ServiceData data = new ServiceData();
//todo 生产数据过程
queue.put(data);
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
消费者代码
import java.util.concurrent.*;
/**
* 消费者
*/
public class DataConsumer implements Runnable {
private BlockingQueue<ServiceData> queue;
public DataConsumer(BlockingQueue<ServiceData> queue) {
this.queue = queue;
}
/**
* 当前任务是否完成
*/
private boolean finished;
public boolean isFinished() {
return finished;
}
/**
* 判断所有消费者都完成任务
* @param consumers
* @return
*/
public static boolean isAllFinished(DataConsumer... consumers) {
for (DataConsumer consumer : consumers) {
if (!consumer.isFinished()) {
return false;
}
}
return true;
}
@Override
public void run() {
//不停消费数据,没有数据时阻塞
while (true) {
try {
ServiceData data = queue.take();
finished = false;
//todo 消费数据过程
}catch (Exception e) {
e.printStackTrace();
}finally {
finished = true;
}
}
}
}
线程池
import java.util.concurrent.*;
public class Test {
public static void main(String[] args) {
//创建一个有三个固定线程的线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
//创建任务队列
BlockingQueue<PdfUrl> queue = new LinkedBlockingQueue<>();
//创建一个生产者
DataProducer producer1 = new DataProducer(queue);
//创建两个消费者
DataConsumer consumer1 = new DataConsumer(queue);
DataConsumer consumer2 = new DataConsumer(queue);
//启动任务
executorService.execute(producer1);
executorService.execute(consumer1);
executorService.execute(consumer2);
//生产者生产完成后,队列空了并且消费完成,则结束
while (true) {
if (queue.isEmpty() && DataConsumer.isAllFinished(consumer1,consumer2)) {
break;
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//关闭线程池,立即stop线程
threadPool.shutdownNow();
}
}
不积跬步无以至千里