内容简介:转载请注明出处:http://zhongmingmao.me/2019/05/26/java-concurrent-producer-consumer/
- 生产者-消费者模式的核心是一个 任务队列
- 生产者线程生产任务,并将任务添加到任务队列中,消费者线程从任务队列中获取任务并执行
- 从 架构设计 的角度来看,生产者-消费者模式有一个很重要的优点: 解耦
- 生产者-消费者模式另一个重要的优点是 支持异步 ,并且能够 平衡 生产者和消费者的 速度差异 (任务队列)
支持批量执行
- 往数据库INSERT 1000条数据,有两种方案
- 第一种方案:用1000个线程并发执行,每个线程INSERT一条数据
- 第二种方案(更优):用1个线程,执行一个批量的SQL,一次性把1000条数据INSERT进去
- 将原来直接INSERT数据到数据库的线程作为生产者线程,而生产者线程只需将数据添加到任务队列
- 然后消费者线程负责将任务从任务队列中批量取出并批量执行
// 任务队列 private BlockingQueue<Task> queue = new LinkedBlockingQueue<>(2000); // 启动5个消费者线程,执行批量任务 public void start() { ExecutorService pool = Executors.newFixedThreadPool(5); for (int i = 0; i < 5; i++) { pool.execute(() -> { try { while (true) { // 获取批量任务 List<Task> tasks = pollTasks(); // 执行批量任务 execTasks(tasks); } } catch (InterruptedException ignored) { } }); } } // 从任务队列中获取批量任务 private List<Task> pollTasks() throws InterruptedException { List<Task> tasks = new LinkedList<>(); // 阻塞式获取一个任务 // 首先采用阻塞式的方式,如果任务队列中没有任务,能够避免无谓的循环 Task task = queue.take(); while (task != null) { tasks.add(task); // 非阻塞式获取一个任务 task = queue.poll(); } return tasks; } // 批量执行任务 private void execTasks(List<Task> tasks) { }
支持分阶段提交
- 写文件如果同步刷盘性能会很慢,对于不是很重要的数据,往往采用 异步刷盘 的方式
- 异步刷盘的时机
- ERROR级别的日志需要立即刷盘
- 数据累积到500条需要立即刷盘
- 存在未刷盘数据,且5秒钟内未曾刷盘,需要立即刷盘
- 该日志组件的异步刷盘本质上是一种 分阶段提交
public class Logger { // 批量异步刷新的数量 private static final int FLUSH_BATCH_SIZE = 500; // 任务队列 private final BlockingQueue<LogMsg> queue = new LinkedBlockingQueue<>(); // 只需要一个线程写日志 private ExecutorService pool = Executors.newFixedThreadPool(1); // 启动写日志线程 public void start() throws IOException { File file = File.createTempFile("test", ".log"); FileWriter writer = new FileWriter(file); pool.execute(() -> { // 未刷盘日志数量 int curIdx = 0; long preFlushTime = System.currentTimeMillis(); while (true) { try { LogMsg logMsg = queue.poll(5, TimeUnit.SECONDS); // 写日志 if (logMsg != null) { writer.write(logMsg.toString()); ++curIdx; } // 如果不存在未刷盘数据,则无需刷盘 if (curIdx <= 0) { continue; } // 异步刷盘规则 if (logMsg != null && logMsg.getLevel() == LEVEL.ERROR || curIdx == FLUSH_BATCH_SIZE || System.currentTimeMillis() - preFlushTime > 5_000) { writer.flush(); curIdx = 0; preFlushTime = System.currentTimeMillis(); } } catch (InterruptedException | IOException ignored) { } finally { try { writer.flush(); writer.close(); } catch (IOException ignored) { } } } }); } private void info(@NonNull String msg) throws InterruptedException { queue.put(new LogMsg(LEVEL.INFO, msg)); } private void error(@NonNull String msg) throws InterruptedException { queue.put(new LogMsg(LEVEL.ERROR, msg)); } } @Data @AllArgsConstructor class LogMsg { private LEVEL level; private String msg; } enum LEVEL { INFO, ERROR }
转载请注明出处:http://zhongmingmao.me/2019/05/26/java-concurrent-producer-consumer/
访问原文「 Java并发 -- 生产者-消费者模式 」获取最佳阅读体验并参与讨论
以上所述就是小编给大家介绍的《Java并发 -- 生产者-消费者模式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Java多线程之并发协作生产者消费者设计模式
- 高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?【石杉的架构笔记】
- Kafka生产者简介
- RocketMQ生产者流程篇
- RocketMQ生产者消息篇
- Java精讲:生产者-消费者
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Deep Learning
Ian Goodfellow、Yoshua Bengio、Aaron Courville / The MIT Press / 2016-11-11 / USD 72.00
"Written by three experts in the field, Deep Learning is the only comprehensive book on the subject." -- Elon Musk, co-chair of OpenAI; co-founder and CEO of Tesla and SpaceX Deep learning is a for......一起来看看 《Deep Learning》 这本书的介绍吧!
在线进制转换器
各进制数互转换器
RGB HSV 转换
RGB HSV 互转工具