浅谈Java线程池是如何运行的

 更新时间:2020年11月27日 11:39:42   作者:caz  
这篇文章主要介绍了浅谈Java线程池是如何运行的,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

异步编程工具在Android开发中目前最被推荐的就是Kotlin协程,在引入Kotlin协程机制前,除了响应式扩展(RxJava)兼任异步编程工具外,Java API中线程与线程池就是最重要异步编程手段。而对于Android平台的Kotlin协程实现来说,依然使用的是线程池来作为任务执行的载体,所以可以将Android平台的Kotlin协程简单的理解是对线程池的一种高度封装。

Executors.newFixedThreadPool(10).asCoroutineDispatcher()
Dispatchers.IO.asExecutor()

因此我们先了解Java线程池是如何运行的,再深入理解Kotlin协程是如何实现的。

从Thread到Executor

线程的创建通过Thread类,为了复用线程而进行池化就有了线程池。线程池带来了两点明显优势:

  • 降低重复创建线程的开销
  • 将任务与线程管理解耦

Executor接口就是第二点的体现。其execute方法用于执行任务,不必关系这个任务执行的载体究竟是什么,到底有没有创建线程。ThreadPoolExecutor实现类就是这个任务执行器的线程池实现。

ThreadPoolExecutor的任务添加与线程复用

 public void execute(Runnable command) {
  if (command == null)
   throw new NullPointerException();
  int c = ctl.get();
  if (workerCountOf(c) < corePoolSize) {
   if (addWorker(command, true))
    return;
   c = ctl.get();
  }//1
  if (isRunning(c) && workQueue.offer(command)) {
   int recheck = ctl.get();
   if (! isRunning(recheck) && remove(command))
    reject(command);
   else if (workerCountOf(recheck) == 0)
    addWorker(null, false);
  }//2
  else if (!addWorker(command, false))
   reject(command);//3
 }

查看execute方法可以清楚了解其运行方式:

  1. 当线程数小于corePoolSize时,创建线程并执行任务;
  2. 若任务未通过步骤1添加,则入队workQueue;(主要逻辑在if的条件判断中,而if内的逻辑处理的是在一些异常下,对入队的回滚或补充创建线程)
  3. 若任务未入队,则仍创建线程(上限为maximumPoolSize)并执行任务,失败则执行拒绝策略。

boolean addWorker(Runnable firstTask, boolean core)就是创建线程的方法,方法中第二个参数代表以corePoolSize还是maximumPoolSize为界,方法内其余创建线程的细节逻辑不深究。但要关注一下线程的封装类Worker,addWorker方法内调用了Worker内被封装线程的start方法,执行Worker的run方法。我们将run方法内的runWorker简化如下:

 void runWorker(Worker w) {
  Runnable task = w.firstTask;
  w.firstTask = null;
  while (task != null || (task = getTask()) != null) {
   task.run();
  }
 }

可以发现,初始任务执行完后,不断通过getTask方法获取任务执行,以此来实现线程的复用,而不是只执行完一个任务就销毁了线程。

另外查看简化后的getTask方法如下:

 private Runnable getTask() {
  boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
  try {
   Runnable r = timed ?
     workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
     workQueue.take();
   if (r != null)
    return r;
  } catch (InterruptedException retry) { }
 }

任务是从阻塞队列workQueue中取出的,并且根据配置allowCoreThreadTimeOut与线程个数是否大于corePoolSize,来决定使用BlockingQueue<Runable>的带超时时间的取任务方法poll,还是阻塞取任务方法take,以实现任务列表为空时适时销毁线程还是阻塞线程。

回过头来看ThreadPoolExecutor的构造方法:

 public ThreadPoolExecutor(int corePoolSize,
        int maximumPoolSize,
        long keepAliveTime,
        TimeUnit unit,
        BlockingQueue<Runnable> workQueue,
        ThreadFactory threadFactory,
        RejectedExecutionHandler handler)

我们可以清楚的明白每个参数的含义,以及它是如何影响线程池中线程的复用了。

到此这篇关于浅谈Java线程池是如何运行的的文章就介绍到这了,更多相关Java 线程池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot 导出数据生成excel文件返回方式

    SpringBoot 导出数据生成excel文件返回方式

    这篇文章主要介绍了SpringBoot 导出数据生成excel文件返回方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • Java并发编程中构建自定义同步工具

    Java并发编程中构建自定义同步工具

    这篇文章主要介绍了Java并发编程中构建自定义同步工具,本文讲解了可阻塞状态依赖操作的结构、有界缓存实现基类示例、阻塞实现方式一:抛异常给调用者、阻塞实现方式二:通过轮询和休眠、阻塞实现方式三:条件队列等内容,需要的朋友可以参考下
    2015-04-04
  • java实现数字猜拳小游戏

    java实现数字猜拳小游戏

    这篇文章主要为大家详细介绍了java实现数字猜拳的小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-06-06
  • java调用微信现金红包接口的心得与体会总结

    java调用微信现金红包接口的心得与体会总结

    这篇文章主要介绍了java调用微信现金红包接口的心得与体会总结,有需要的朋友可以了解一下。
    2016-11-11
  • Springboot在有参构造方法类中使用@Value注解取值

    Springboot在有参构造方法类中使用@Value注解取值

    这篇文章主要介绍了Springboot在有参构造方法类中使用@Value注解取值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • idea快速搭建springboot项目的操作方法

    idea快速搭建springboot项目的操作方法

    下面小编就为大家分享一篇idea快速搭建springboot项目的操作方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • 使用javax.sound实现简单音频播放

    使用javax.sound实现简单音频播放

    这篇文章主要为大家详细介绍了使用javax.sound实现简单音频播放,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • Springboot中依赖注入的三种方式详解

    Springboot中依赖注入的三种方式详解

    这篇文章主要介绍了Springboot中依赖注入的三种方式详解,Setter Injection需要依赖@Autowired注解,使用方式与Field Injection有所不同,Field Injection时@Autowired是用在成员变量上,需要的朋友可以参考下
    2023-09-09
  • SpringBoot缓存Ehcache的使用详解

    SpringBoot缓存Ehcache的使用详解

    EhCache、Redis比较常用,使用Redis的时候需要先安装Redis服务器,本文给大家介绍SpringBoot缓存Ehcache的使用详解,感兴趣的朋友跟随小编一起看看吧
    2022-03-03
  • Spring Data Jpa框架最佳实践示例

    Spring Data Jpa框架最佳实践示例

    这篇文章主要为大家介绍了Spring Data Jpa框架最佳实践示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-02-02

最新评论