久趣下载站

当前位置: 首页 » 游戏攻略 » 如何创建线程池及其影响

如何创建线程池及其影响

在学习线程时,我们了解了创建线程的不同方式,比如继承Thread类、实现Runnable接口、Callable接口等。针对线程池的使用,我们提供了两种构造线程池的方法:



方法一:

通过ThreadPoolExecutor构造函数来创建(首选)


这是JDK中最核心的线程池工具类,提供了丰富的可设置的线程池构造参数,如设置线程池大小、等待队列、非核心线程存活时间、创建线程的工厂类、拒绝策略等。

通过构造方法,可以给整个线程池设置大小、等待队列、非核心线程存活时间、创建线程的工厂类、拒绝策略等。具体参数描述可见


第六问


,该参数与线程池中的对应关系可见下图。



方法二:

通过 Executor 框架的工具类 Executors 来创建(不推荐)


Executors 是java并发工具包中的静态工厂类,提供了丰富的创造线程池的方法,但不推荐使用。

  • newFixedThreadPool:创建定长线程池,该线程池中的线程数量始终不变。当有新任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。当线程发生错误结束时,线程池会补充一个新的线程。
  • newCachedThreadPool:创建可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,所有线程在当前任务执行完毕后,将返回线程池进行复用,线程池的容量不限制。
  • newScheduledThreadPool:创建定长线程池,可执行周期性的任务。
  • newSingleThreadExecutor:创建单线程的线程池,只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行。
  • newWorkStealingPool:任务可窃取线程池,不保证执行顺序,当有空闲线程时会从其他任务队列窃取任务执行,适合任务耗时差异较大的场景。



为何很多大厂都禁止使用Executors 创建线程池呢?

大部分公司已经不建议采用Executors提供的方法创建线程池了。如果深入研究Executors方法的底层实现,就会发现原因。像FixedThreadPool和SingleThreadExecutor这两个方法内使用的是无界的LinkedBlockingQueue存储任务,任务队列最大长度为Integer.MAX_VALUE,这样可能会堆积大量的请求,从而导致OOM。

而CachedThreadPool使用的是同步队列SynchronousQueue,允许创建的线程数量也为Integer.MAX_VALUE,如果任务数量过多且执行速度较慢,可能会创建大量的线程,从而导致OOM。其他方法所提供的均是这种


无界任务队列


,在高并发场景下导致OOM的风险很大。

猜你喜欢
本类排行