今天对五种常见的java内置线程池进行讲解。

线程使用的demo

public static void cache() {ExecutorService pool = Executors.newCachedThreadPool();long start = System.currentTimeMillis();pool.execute(() -> {int sum = 0;for (int i = 0; i < 10; i++) {sum = (int) Math.sqrt(i * i - 1 + i);System.out.println(sum);}});System.out.println("cache: " + (System.currentTimeMillis() - start));}

newCachedThreadPool

  • 重用之前的线程
  • 适合执行许多短期异步任务的程序。
  • 调用 execute() 将重用以前构造的线程
  • 如果没有可用的线程,则创建一个新线程并添加到池中
  • 默认为60s未使用就被终止和移除
  • 长期闲置的池将会不消耗任何资源

源码:

public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());}

通过源码可以看出底层调用的是ThreadPoolExecutor方法,传入一个同步的阻塞队列实现缓存。

下面说一下ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);}

通过源码可以看出,我们可以传入线程池的核心线程数(最小线程数),最大线程数量,保持时间,时间单位,阻塞队列这些参数,最大线程数设置为jvm可用的cpu数量为最佳实践

newWorkStealingPool

  • 获取当前可用的线程数量进行创建作为并行级别
  • 使用ForkJoinPool

源码:

public static ExecutorService newWorkStealingPool() {return new ForkJoinPool(Runtime.getRuntime().availableProcessors(),ForkJoinPool.defaultForkJoinWorkerThreadFactory,null, true);}

通过源码可以看出底层调用的是ForkJoinPool线程池

下面说一下ForkJoinPool

public ForkJoinPool(int parallelism,ForkJoinWorkerThreadFactory factory,UncaughtExceptionHandler handler,boolean asyncMode) {this(checkParallelism(parallelism),checkFactory(factory),handler,asyncMode ? FIFO_QUEUE : LIFO_QUEUE,"ForkJoinPool-" + nextPoolId() + "-worker-");checkPermission();}

使用一个无限队列来保存需要执行的任务,可以传入线程的数量,不传入,则默认使用当前计算机中可用的cpu数量,使用分治法来解决问题,使用fork()和join()来进行调用

newSingleThreadExecutor

  • 在任何情况下都不会有超过一个任务处于活动状态
  • 与newFixedThreadPool(1)不同是不能重新配置加入线程,使用FinalizableDelegatedExecutorService进行包装
  • 能保证执行顺序,先提交的先执行。
  • 当线程执行中出现异常,去创建一个新的线程替换之
    源码:
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));}

newFixedThreadPool

  • 创建重用固定数量线程的线程池,不能随时新建线程
  • 当所有线程都处于活动状态时,如果提交了其他任务,
    他们将在队列中等待一个线程可用
  • 线程会一直存在,直到调用shutdown

源码:

public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}

newScheduledThreadPool

  • 设定延迟时间,定期执行
  • 空闲线程会进行保留

源码:

return new ScheduledThreadPoolExecutor(corePoolSize);

通过源码可以看出底层调用的是一个ScheduledThreadPoolExecutor,然后传入线程数量

下面来介绍一下ScheduledThreadPoolExecutor

public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());}

通过源码可以看出底层调用了ThreadPoolExecutor,维护了一个延迟队列,可以传入线程数量,传入延时的时间等参数,下面给出一个demo

public static void main(String[] args) {ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);for (int i = 0; i < 15; i = i + 5) {pool.schedule(() -> System.out.println("我被执行了,当前时间" + new Date()), i, TimeUnit.SECONDS);}pool.shutdown();}

执行结果

我被执行了,当前时间Fri Jan 12 11:20:41 CST 2018
我被执行了,当前时间Fri Jan 12 11:20:46 CST 2018
我被执行了,当前时间Fri Jan 12 11:20:51 CST 2018

有的小伙伴可能会用疑问,为什么使用schedule()而不使用submit()或者execute()呢,下面通过源码来分析

    public void execute(Runnable command) {schedule(command, 0, NANOSECONDS);}public Future<?> submit(Runnable task) {return schedule(task, 0, NANOSECONDS);}

通过源码可以发现这两个方法都是调用的schedule(),而且将延时时间设置为了0,所以想要实现延时操作,需要直接调用schedule()

下面我们再来分析一下submit()和execute()的以及shutdown()和shutdownNow()的区别

  • submit(),提交一个线程任务,可以接受回调函数的返回值吗,适用于需要处理返回着或者异常的业务场景
  • execute(),执行一个任务,没有返回值
  • shutdown(),表示不再接受新任务,但不会强行终止已经提交或者正在执行中的任务
  • shutdownNow(),对于尚未执行的任务全部取消,正在执行的任务全部发出interrupt(),停止执行

五种线程池的适应场景

  1. newCachedThreadPool:用来创建一个可以无限扩大的线程池,适用于服务器负载较轻,执行很多短期异步任务。
  2. newFixedThreadPool:创建一个固定大小的线程池,因为采用无界的阻塞队列,所以实际线程数量永远不会变化,适用于可以预测线程数量的业务中,或者服务器负载较重,对当前线程数量进行限制。
  3. newSingleThreadExecutor:创建一个单线程的线程池,适用于需要保证顺序执行各个任务,并且在任意时间点,不会有多个线程是活动的场景。
  4. newScheduledThreadPool:可以延时启动,定时启动的线程池,适用于需要多个后台线程执行周期任务的场景。
  5. newWorkStealingPool:创建一个拥有多个任务队列的线程池,可以减少连接数,创建当前可用cpu数量的线程来并行执行,适用于大耗时的操作,可以并行来执行

转自:https://www.jianshu.com/p/135c89001b61

五种线程池的对比与使用相关推荐

  1. java线程池详解及五种线程池方法详解

    基础知识 Executors创建线程池 Java中创建线程池很简单,只需要调用Executors中相应的便捷方法即可,比如Executors.newFixedThreadPool(int nThrea ...

  2. Java四种线程池使用

    Java 四种线程池的使用 https://juejin.im/post/59df0c1af265da432f301c8d 1,线程池的作用  线程池作用就是限制系统中执行线程的数量.  根据系统的环 ...

  3. Java多线程系列(五):线程池的实现原理、优点与风险、以及四种线程池实现

    为什么需要线程池 我们有两种常见的创建线程的方法,一种是继承Thread类,一种是实现Runnable的接口,Thread类其实也是实现了Runnable接口.但是我们创建这两种线程在运行结束后都会被 ...

  4. [转]new Thread的弊端及Java四种线程池的使用

    介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端 执行一个异步任务你还只是如下new ...

  5. Java ExecutorService四种线程池的例子与说明

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() {@Overridepublic void run() {// ...

  6. Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor...

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java new Thread(new Runnable() {@Override public void run ...

  7. Android AsyncTask两种线程池分析和总结

    转自:http://bbs.51cto.com/thread-1114378-1-1.html Android AsyncTask两种线程池分析和总结 (一)    前言 在android Async ...

  8. Android之AsyncTask两种线程池分析和总结

    Android AsyncTask两种线程池分析和总结 (一)    前言 在android AsyncTask里面有两种线程池供我们调用 1.    THREAD_POOL_EXECUTOR, 异步 ...

  9. winform判断线程有没有完成_并发编程系列1:线程池的架构实现、大小配置、及四种线程池使用...

    △ 公众号回复关键词"架构" 即可领取<1500+BAT架构及面试专题合集> 本篇为线程池系列文章之一,不经常使用线程池的童鞋,还有对几种线程的使用不甚了解的童鞋,可以 ...

最新文章

  1. 天翼云从业认证(1.4)计算机网络
  2. PostgreSQL windows下安装出现问题的解决办法
  3. 超大福利 | 这款免费 Java 在线诊断利器,不用真的会后悔!
  4. java boxplot_java – 具有多个类别的Boxplots的JFreeChart缩放
  5. 五年级计算机课程内容,五年级信息技术教学计划
  6. 系统分析员备考之经济管理篇(一)
  7. 【百度贾磊】汉语语音识别技术重大突破:LSTM+CTC详解(22PPT)
  8. python docx 合并文档 图片_使用python抓取大量简历文档内数据(word:docx;pdf;图片等)输出表格文件...
  9. 敏捷开发中XP与SCRUM的区别
  10. 谁抢光了你的火车票?
  11. LDC1101 LDC1314 LDC1614 1612 线圈感应测试(PCB+源码)
  12. Postman如何设置为中文
  13. 什么?你居然不会微信分身
  14. 灾难恢复_灾难恢复–以及如何避免需要它!
  15. 2021年安全员-C证(山东省-2021版)找解析及安全员-C证(山东省-2021版)模拟考试
  16. 多元积分学及其应用复盘
  17. ERP :金蝶软件财务快捷键
  18. 如何使用pdfFactory Pro编辑及打印图片?
  19. python与土木工程_从土木工程转型到人工智能的经历
  20. Metal 框架之渲染管线渲染图元

热门文章

  1. react textarea 空格为什么不换行_你需要的 React + TypeScript 50 条规范和经验
  2. r语言清除变量_如何优雅地计算多变量 | R语言进阶
  3. kcbzps oracle_Oracle 11g DRCP配置与使用(上)
  4. 信号中断 与 慢系统调用
  5. 川职院单招计算机考什么专业,四川单招考什么科目
  6. if 组件是否存在_UE4 UMG简介+Slate组件问题排查
  7. eclipse编译java项目class文件_动态编译 Java 代码以及生成 Jar 文件
  8. xps13 linux 硬盘分区,在xps13上安装ubuntu16.04教程
  9. 【转】matlab函数编译成dll供Cpp调用的方法
  10. ABP入门系列(18)—— 使用领域服务