2023-2更文5-forkJoinPool线程池

100 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情

forkJoinPool线程池

前文

相比于常规的ThreadPoolExecutor线程池创建器,forkJoinPool是另一种特殊情形的线程池,也就是对于提交上来的任务,线程池本身会进行分治处理,将任务分发给不同的线程来执行,最后在汇总执行结果。

forkJoinPool的使用

对于常规的任务来说,如果我们需要聚合多个线程的执行结果,一般需要采用countDownLatch等线程处理关键字,当所有线程执行结束后,统一进行线程后续的结果累计,或者采用线程锁等方式,保证所有线程执行后进行结果的计算。而本文中所提到的forkJoinPool,则是自动将任务本身进行分治,线程池直接会将任务分发给不同的线程进行处理,避免了我们手动进行汇聚结果的操作。而具体需要切片为多少个线程,线程池也会自动帮助我们匹配最优的策略,实际上也是在递归的不停进行新线程中任务的执行。

ForkJoinPool forkJoinPool = new ForkJoinPool();
forkJoinPool.invoke(new Task());

上面代码展示了forkJoinPool最基础的一种使用方式。而对于任务的提交,forkJoinPool也包含execute、submit以及invoke三种提交方式。三种提交方式的区别如下:

  • execute 直接执行且任务无返回值,也就是一种异步执行的方式
  • submit 根据源码中与execute的对比,增加了返回task的操作,也就是异步执行后可以获取到执行的结果值
  • invoke 与上述两种方式又有所不同,在执行后返回的内容是task.join,而其中的代码逻辑则是会一直保持阻塞状态,直到程序完全执行完毕

上述的三种不同的逻辑,需要我们在使用的过程中根据自己需要的场景进行区分,选择最适合自己业务需求的方案,根据异步、返回值、阻塞等方面来分析我们的程序应该采用哪种方案。

forkJoinPool的线程池由于其特殊的特性,也是一种常用的线程池,主要是出现在某些特定场景中。例如我们常用的流并行计算,其实在底层中便应用了forkJoinPool线程池。

总结

本文主要是对于forkJoinPool的相关知识进行了一定基础的介绍,由于其特殊的特性在某些场景有具备应用的价值,开发过程中可以按照需求采用这种线程池,可以节省很多的代码量且提高程序的执行效率。