目录
前言:
因为同事说,可以用阻塞队列来实现生产消费,因为消费waterdrop得控制一下消费的量。
可以这样实现一个阻塞队列,不过使用线程池其实也可以的,线程池使用核心线程数来限制一下消费~后面跑跑看看效果吧。
回到正题,这个demo测出来好玩的东西
执行结果
首先run方法中执行到末尾,会被自动会受到,而核心线程去执行任务,这个核心线程不会销毁。生产者我这边写法是发布完就销毁掉了,跟我的使用场景有关。
queue.offer(data, 2, TimeUnit.SECONDS)
queue.offer(data)
这两个是有区别的,第一个是一共等两秒,放不进去再false
第二个就是放不进去直接false
比如审核通过,直接发布任务,然后执行发布。
Producer Thread id: 13 started!
Producer Thread id: 14 started!
Consumer Thread id: 15 started!
producer 14 put data : 2
Producer Thread id: 14end!
Producer Thread id: 14 started!
当前阻塞队列已满, 进行重试
producer 13 put data : 1
Producer Thread id: 13end!
消费taskID: 1 进行执行service
Producer Thread id: 13 started!
producer 13 put data : 4
Producer Thread id: 13end!
Producer Thread id: 13 started!
当前阻塞队列已满, 进行重试
消费taskID: 2 进行执行service
producer 14 put data : 3
Producer Thread id: 14end!
Producer Thread id: 14 started!
当前阻塞队列已满, 进行重试
当前阻塞队列已满, 进行重试
消费taskID: 4 进行执行service
消费taskID: 3 进行执行service
producer 14 put data : 6
Producer Thread id: 14end!
消费taskID: 6 进行执行service
Producer Thread id: 14 started!
producer 14 put data : 7
Producer Thread id: 14end!
Producer Thread id: 14 started!
producer 14 put data : 8
Producer Thread id: 14end!
当前阻塞队列已满, 进行重试
消费taskID: 7 进行执行service
producer 13 put data : 5
消费taskID: 8 进行执行service
Producer Thread id: 13end!
消费taskID: 5 进行执行service
消费者
package com.dk.learndemo.queue;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
/**
* @desc: Consumer
* @date: 2021/3/29 3:34 下午
*/
public class Consumer implements Runnable {
private BlockingQueue<Data> queue;
public Consumer(BlockingQueue<Data> queue) {
this.queue = queue;
}
@Override
public void run() {
System.out.println("Consumer Thread id: " + Thread.currentThread().getId() + " started!");
Random r = new Random();
while (true) {
try {
Data data = queue.take();
if (data != null) {
//取出数据成功,输出计算平方值
System.out.println("消费taskID: " + data.getNum() + " 进行执行service");
}
//随机睡眠一定时间
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.interrupted();
}
}
}
}
生产者
package com.dk.learndemo.queue;
import java.util.concurrent.BlockingQueue;
/**
* @desc: Producer
* @date: 2021/3/29 3:34 下午
*/
public class Producer implements Runnable {
private volatile boolean isRunning = true;
BlockingQueue<Data> queue;
private volatile Integer taskId;
private Integer maxRetryCount = 0;
public Producer(BlockingQueue<Data> queue, Integer taskId) {
this.queue = queue;
this.taskId = taskId;
}
/**
* 如果比如放10次或者更多次都不成功,那么则告警
* */
@Override
public void run() {
Data data = null;
System.out.println("Producer Thread id: " + Thread.currentThread().getId() + " started!");
try {
while (isRunning) {
data = new Data(taskId);
// if (queue.offer(data, 2, TimeUnit.SECONDS)) {
if (queue.offer(data)) {
//生产者向bq中添加数据
System.out.println(
"producer " + Thread.currentThread().getId() + " put data : " + data
.getNum());
isRunning = false;
} else if (maxRetryCount >= 5) {
// 超过5次都没有成功,可以进行告警
System.out.println(
"发生了告警!!! " + "Producer Thread id: " + Thread.currentThread().getId());
isRunning = false;
} else {
System.out.println("当前阻塞队列已满, 进行重试");
++maxRetryCount;
Thread.sleep(100);
}
}
System.out.println("Producer Thread id: " + Thread.currentThread().getId() + "end!");
} catch (InterruptedException e) {
e.printStackTrace();
Thread.interrupted();
}
}
public void stop() {
isRunning = false;
}
}
pojo
package com.dk.learndemo.queue;
/**
* @desc: Data
* @date: 2021/3/29 3:36 下午
*/
public class Data {
int taskId;
public Data(int num) {
this.taskId = num;
}
public Data(String str) {
this.taskId = Integer.valueOf(str);
}
public int getNum() {
return taskId;
}
}
main
package com.dk.learndemo.queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @desc: QueueMain
* @date: 2021/3/29 3:34 下午
*/
public class QueueMain {
/**
* 线程池默认的拒绝策略:线程池的默认拒绝策略为AbortPolicy,即丢弃任务并抛出RejectedExecutionException异常
* <p>
* 这边对于生产者,只要放到了queue里面,他的生命周期就结束了,完成了他的任务
*/
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Data> queue = new LinkedBlockingQueue<>(2);
// 生产者也是会被销毁掉的
ExecutorService producerExecutor = new ThreadPoolExecutor(2, 2,
0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(10));
// customer 假如只有两个个 永远不销毁
ExecutorService customerExecutor = new ThreadPoolExecutor(2, 2,
0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(10));
Producer producer1 = new Producer(queue, 1);
Producer producer2 = new Producer(queue, 2);
Producer producer3 = new Producer(queue, 3);
Producer producer4 = new Producer(queue, 4);
Producer producer5 = new Producer(queue, 5);
Producer producer6 = new Producer(queue, 6);
Producer producer7 = new Producer(queue, 7);
Producer producer8 = new Producer(queue, 8);
// customer 永远不关闭
Consumer consumer1 = new Consumer(queue);
Consumer consumer2 = new Consumer(queue);
producerExecutor.execute(producer1);
producerExecutor.execute(producer2);
producerExecutor.execute(producer3);
producerExecutor.execute(producer4);
producerExecutor.execute(producer5);
producerExecutor.execute(producer6);
producerExecutor.execute(producer7);
producerExecutor.execute(producer8);
//线程池
customerExecutor.execute(consumer1);
// customerExecutor.execute(consumer2);
}
}