当前位置 博文首页 > JavaEdge全是干货的技术号:阿里P8终于讲明白了生产者-消费者模

    JavaEdge全是干货的技术号:阿里P8终于讲明白了生产者-消费者模

    作者:[db:作者] 时间:2021-07-21 12:41

    核心是一个任务队列,生产者线程生产任务,并将任务添加到任务队列中,而消费者线程从任务队列中获取任务并执行。该模式有如下优点:

    解耦

    解耦的一个关键就是组件之间的依赖关系和通信方式必须受限。在生产者-消费者模式中,生产者和消费者没有任何依赖关系,它们彼此之间的通信只能通过任务队列,所以生产者-消费者模式是一个不错的解耦方案。

    异步

    平衡生产者和消费者的速度差异。生产者线程只需要将任务添加到任务队列,无需等待任务被消费者线程执行完,即任务的生产和消费是异步的。

    异步化处理最简单的方式就是创建一个新的线程去处理,那中间加个“任务队列”究竟有什么用呢?主要还是用于平衡生产者和消费者的速度差异。
    假设生产者速率慢,消费者速率高,1:3,若生产者有3个线程

    • 采用创建新线程,则会创建3个子线程
    • 采用生产者-消费者模式,消费线程只需要1个

    由于Java线程和os线程一一对应,线程创建得太多,会增加上下文切换成本。生产者-消费者模式恰好能支持使用合适数量的线程。

    批量执行

    若使用轻量级线程,就没有必要平衡生产者和消费者速度差异,那是否说明生产者-消费者模式在性能优化方面就无用武之地?
    不是,有一类并发场景应用生产者-消费者模式就有奇效:批量执行任务。

    比如要在DB INSERT 1000条数据,有如下方案:

    • 用1000个线程并发执行,每个线程INSERT一条数据
    • 用1个线程,执行一个批量SQL,一次性把1000条数据INSERT进去
      该方案效率更高,这就是批量执行场景。

    分阶段

    写文件时,若同步刷盘,性能会很低,所以对不太重要数据,一般采用异步刷盘。
    某日志组件采用异步刷盘方式,不同刷盘时机提交刷盘任务。

    cs