灯下黑?原来线程池是最典型生产消费者模式

如题所述

第1个回答  2022-07-16

使用Thread开启线程:

当然,一般我们会执行start方法。

若使用Thread开启线程: 每一次子线程均需要经历创建和销毁的生命周期,性能不好。

为了解决这个问题,JDK设计出线程池。

JDK的BlockingQueue,天生实现的是生产者-消费者模型,即队列满了put队列会被阻塞;队列空了后get方法会被阻塞。

线程池中Worker线程开启后。使用while循环消费BlockingQueue中的Runnable。若 while循环时得到的任务为空,那么便去关闭Worker线程 。这也就是 最大线程数 超过空闲时间的核心线程数 能自动回收的原因。

核心线程数的空闲时间 KeepAliveTime 。其实就是阻塞队列获取Running的最大等待时间。当配置了该参数且超过最大等待时间,那么返回一个null任务。而worker线程的run方法中的while循环得到null时,便会结束这个worker线程。

poll获取到的元素为空,那么便会结束监听,worker线程的run方法执行完毕。

当返回null时,由“work线程将开启while循环的监听”可值,将结束worker线程的监听操作。

生产者向BlockingQueue中放入消息时,并没有使用put方法,而是使用的offer方法。

拒绝策略: 因为offer方法返回false,说明阻塞队列已经满了,若最大线程数大于核心线程数,那么继续开启Worker线程。若开启的是最大线程数的Worker线程,那么就会执行配置的拒绝策略。

上文我们得知,生产者放入queue时使用的是offer方法,当阻塞队列满了之后,直接返回false。我们可以采用put的方式,将主线程阻塞。不在向BlockingQueue中填充任务。

JAVA并发(12)— Lock实现生产者消费者
JAVA并发(13)— ThreadPoolExecutor的实现原理(源码分析)

相似回答
大家正在搜