美文网首页
线程池查漏补缺

线程池查漏补缺

作者: xhrg | 来源:发表于2019-01-25 10:34 被阅读0次

tomcat线程池和jdk线程池区别

概述

  1. 线程池是什么,为什么要线程池
  2. jdk有哪些线程池和原理
  3. 第三方中间件的线程池特点
  • tomcat线程池
  • quartz线程池
  1. 线程池展望

线程池是什么,为什么要线程池

我们在项目启动后,因为CPU是多核的,为了充分利用CPU,可能需要启动多个线程去处理任务。频繁的创建销毁线程是有开销的。所以需要创建线程后缓存住,让线程可以频繁的处理各种任务。这个时候就需要用线程池。线程池一般会缓存住N个线程,然后往线程池里面扔任务Runnable,线程不断的处理任务。处理完了后停留在那里等待。

jdk有哪些线程池和原理

jdk线程池主要入口是在java.util.concurrent.Executors,其中包含

  • Executors.newFixedThreadPool 固定核心数的线程池,有多余任务往无界队列中放

  • Executors.newSingleThreadExecutor 单线程的线程池,有多余任务往无界队列中放

  • Executors.newCachedThreadPool 有任务来就开辟新的线程,不缓存任务,不缓存线程。

  • Executors.newSingleThreadScheduledExecutor 单线程的延迟线程池,也就是说可以指定任务N秒后周期性执行。

  • Executors.newScheduledThreadPool N线程的延迟线程池,也就是说可以指定任务N秒后周期性执行。
    * 这个线程池内部依赖于ScheduledThreadPoolExecutor,队列依赖于ScheduledThreadPoolExecutor.DelayedWorkQueue,这个队列在take的时候,会根据你添加任务的时候的时间做一个awaitNanos(delay),代码见该类的take方法。故而实现了延迟执行。

  • Executors.unconfigurableExecutorService

线程池的主要原理是在ThreadPoolExecutor这个类中。ThreadPoolExecutor有以下概念

  • corePoolSize

  • maximumPoolSize

  • keepAliveTime

  • workQueue

这四个概念一起解释,corePoolSize指的是线程池核心数,当有任务进来的时候,如果开辟的线程少于该值,就不断开新线程去处理,直到该值。如果到了该值之后,就把新的任务存放在队列中,也就是workQueue中,去存放的过程会成功和失败,如果成功就存放在队列中了,如果失败,就继续开辟线程去执行。直到线程数等于maximumPoolSize,便不再开新线程。如果队列满了,线程也到最大值了,这个时候,就进行拒绝策略。

  • AbortPolicy 默认策略,抛出异常RejectedExecutionException。

  • DiscardPolicy 什么都不做

  • DiscardOldestPolicy 把任务头丢掉,然后再把任务加入队列

  • CallerRunsPolicy 主线程自己去执行任务

  • RejectHandler 自己实现

原理大致说明。ThreadPoolExecutor这个类除了参数那些参数外,还有HashSet<Worker> workers,参数,该参数和线程一一对应,也就是说线程池里面的线程就是worker,当任务进来后会和corePoolSize比较,继而新建或者申请worker。新建的线程会不断的从任务队列去拿任务,拿任务有超时时间,就是刚才说到的keepAliveTime,到达时间后,如果说当前线程数大于corePollSize,则自己退出该线程。没有大于则继续循环运行,继续循环运行就是在死循环中去拿队列。

第三方中间件的线程池特点

tomcat线程池

tomcat的线程池是StandardThreadExecutor类,该类的属性也是ThreadPoolExecutor,不过是把ThreadPoolExecutor动态设置参数暴露出来了。所以StandardThreadExecutor类可以动态的修改核心数,最大数。并且该类的阻塞队列使用的是继承自LinkedBlockingQueue的TaskQueue。TaskQueue的核心在于,只要运行当前池子的线程小于maximumPoolSize,就拒绝你加入队列。我们知道线程的数量和IO密集有关系,tomcat这种IO密集型的中间件,适合更多的线程。这里的线程数是maxThreads,该值默认200,tomcat可以配置。

public boolean offer(Runnable o) {
       //这个类是TaskQueue的的方法,我们知道,线程池,是先加入队列,失败后再开线程直到max数。
        if (parent==null) return super.offer(o);
        // 若运行线程为最大线程数,说明线程已经最大了,没办法,还是扔队列吧。
        if (parent.getPoolSize() == parent.getMaximumPoolSize()) return super.offer(o);
        //若任务数小于线程数,直接扔队列,扔队列后,那些闲着的线程自然会取。没必要返回false,让其再重开线程。
        if (parent.getSubmittedCount()<(parent.getPoolSize())) return super.offer(o);
        // 发现运行线程数少于池最大线程数,拒绝加入队列,让线程池继续开线程。
        if (parent.getPoolSize()<parent.getMaximumPoolSize()) return false;
        //if we reached here, we need to add it to the queue
        return super.offer(o);
    }

quartz线程池

quartz线程池是在org.quartz.simpl.SimpleThreadPool

该线程池非常简单,初始化的时候新建N个线程。这个线程是在线程池初始化的时候就新建。然后把线程放在availWorkers中,如果有任务进来,就从availWorkers拿出1个线程放进busyWorkers,然后把任务给该线程执行。执行完了之后返回给availWorkers中。如果线程满了,主线程扔任务的时候,会检查availWorkers的size,当size<1的时候,停半秒继续检查availWorkers直到有可用才运行任务。

线程池展望

相关文章

  • 线程池查漏补缺

    tomcat线程池和jdk线程池区别 概述 线程池是什么,为什么要线程池 jdk有哪些线程池和原理 第三方中间件的...

  • 硬核补充,再探Android线程池

    前言 在之前的查漏补缺,不在线程池上掉链子-初探Android线程池文章中,由于时间原因,只是对Android中的...

  • iOS 查漏补缺 - 线程

    多线程是我们开发和面试中都会遇到的一个重要概念,相比于其他编程语言和平台,iOS 的多线程使用起来要比较友好和易用...

  • 【Android面试查漏补缺】之事件分发机制详解

    前言 查漏补缺,查漏补缺,你不知道哪里漏了,怎么补缺呢?本文属于【Android面试查漏补缺】系列文章第一篇,持续...

  • 查漏补缺

    如果想让HTML5标签兼容低版本浏览器的话,可以使用 html5shiv js来实现。注意:一定要把它引入到前面。...

  • 查漏补缺

    图文环绕和浮动 最初的CSS只是用来写文章,熟练使用float和clear两个属性来布局: float属性:指定一...

  • 查漏补缺

    1.js字符串转换成数字与数字转换成字符串的实现方法https://www.2cto.com/kf/201612/...

  • 查漏补缺

    浮动原理 1.使用之初:是为了让文字环绕图片,并且不会遮住文字。如果让图片与文字有间距,我们在浮动元素上添加。2....

  • 查漏补缺

    今天数学老师外出学习,我用了一上午的时间给孩子们查漏补缺。 首先,训练朗读:从段落与段落之间的大停顿...

  • 查漏补缺

    1 Python提供了ord()和chr()函数,可以把字母和对应的数字相互转换2 写 u'中' 和 u'\u4e...

网友评论

      本文标题:线程池查漏补缺

      本文链接:https://www.haomeiwen.com/subject/vocmjqtx.html