线程池ThreadPool和ForkJoinPool学习

本文深入探讨了线程池技术,重点分析了Java中的ThreadPool和ForkJoinPool。线程池包括ThreadPoolManager、工作线程、任务接口和任务队列。ForkJoinPool引入了工作窃取机制,适用于可分解的大任务,并在多CPU环境中表现出优越性能。对比分析显示,ThreadPool适合阻塞时延较长的任务,而ForkJoinPool则适合快速处理或可分解任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、线程池技术

一个线程池包括以下四个基本组成部分:

  • ThreadPool(线程池管理器):用于创建并管理线程池;
  • PoolWorker(工作线程):线程池中的线程,没有任务时处于等待状态;可以循环执行任务;
  • Task(任务接口):每个任务必须实现的接口,以便工作线程调度任务的执行;
  • taskQueue(任务队列):用于存放处于等待的工作线程任务;
二、ForkJoinPool

ForkJoinPool是JDK7引入的线程池。它的核心思想是将大任务分解成多个小任务(fork),由线程池分别执行每个小任务,等待小任务都执行完之后再把它们的结果汇总起来(join)作为大任务的结果。同时它也提供了基本的线程池功能,支持设置最大并发线程数,支持任务缓存等待,支持线程池停止,支持线程池使用情况监控等。也是AbstractExecutorService的子类,引入了“工作窃取”机制,在多CPU计算机上处理性能更佳。

work-stealing(工作窃取机制)

工作窃取机制是ForkJoinPool提供的一个更有效的利用线程的机制,当ThreadPoolExecutor还在用单个队列存放任务时,ForkJoinPool已经分配了与线程数相等的队列,当有任务加入线程池时,会被平均分配到对应的队列上,各线程进行正常工作,当有线程提前完成时,会从队列的末端“窃取”其他线程未执行完的任务,当任务量特别大时,CPU多的计算机会表现出更好的性能。

三、分析对比
1、应用场景对比
  • ThreadPool
    • 常用于线程并发,阻塞时延较长的任务。这种任务一般要求的线程个数较多;
  • ForkJoinPool
    • 用于大任务可分解成小任务,一般是非阻塞的、可以快速处理的任务;或者阻塞时延较小的任务。
2、基本功能原理
  • ThreadPool
    • 其思想就是实现造出一批线程放到一个集合中,等到有任务来的时候,直接从线程集合中取出一个线程执行任务。这样就把每个线程的创建、连接、销毁等过程统一管理,节省系统时间,提高系统稳定性。
  • ForkJoinPool
    • 类似于MapReduce任务分解聚合模式, ForkJoinPool采用先将大任务fork成多个小任务,然后再将每个小人物的接口join在一起,进而得出大任务的结果。
3、阻塞队列个数
  • ThreadPool
    • 一般是一个阻塞队列。阻塞队列的类型有:
      • ArrayBlockingQueue :是一个有界缓存队列,可以指定缓存队列的大小。当正在执行的线程数等于核心线程数时,新的任务会放到ArrayBlockingQueue队列中,当ArrayBlockingQueue队列已满时,会新开线程执行任务,等到线程数等于最大线程数时,再进来的任务时ArrayBlockingQueue就会报错;
      • LinkedBlockingDeque :是一个无界缓存等待队列,当前执行的线程数等于核心线程数时,新来的任务就会在LinkedBlockingDeque队列中等待(从现像上看使用该缓存队列时最大线程数参数相当于无效了);
      • SynchronousQueue :SynchronousQueue没有容量,是无缓冲等待队列,是一个不存储元素的阻塞队列,会直接将任务交给消费者,必须等队列中的添加元素被消费后才能继续添加新的元素。
  • ForkJoinPool
    • 每个线程都有一个队列。如果一个线程的队列执行完成,可以从其他线程队列的末尾拿出一个任务执行;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值