《重新学习多线程》-- 任务调度线程池以及Tomcat线程池

228 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情

任务调度线程池

在『任务调度线程池』功能加入之前,可以使用 java.util.Timer 来实现定时功能,Timer 的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。

timer

carbon (20).png

当timer中的一个任务出现错误,之后的任务将无法继续执行

ScheduledExecutorService

carbon (21).png 当一个线程出现错误,其他任务可以继续执行

循环执行

carbon (22).png

如果代码执行时间大于循环时间,则循环时间为代码执行时间

scheduleAtFixedRate 为代码执行时间 + 循环时间

如何让每周四 18:00:00 定时执行任务?

carbon (23).png

TomCat线程池

Tomcat 在哪里用到了线程池呢

  • LimitLatch 用来限流,可以控制最大连接个数,类似 J.U.C 中的 Semaphore 后面再讲

  • Acceptor 只负责【接收新的 socket 连接】

  • Poller 只负责监听 socket channel 是否有【可读的 I/O 事件】

  • 一旦可读,封装一个任务对象(socketProcessor),提交给 Executor 线程池处理

  • Executor 线程池中的工作线程最终负责【处理请求】

Tomcat 线程池扩展了 ThreadPoolExecutor,行为稍有不同

  • 如果总线程数达到 maximumPoolSize

    • 这时不会立刻抛 RejectedExecutionException 异常

    • 而是再次尝试将任务放入队列,如果还失败,才抛出 RejectedExecutionException 异常

源码 tomcat-7.0.42

carbon (24).png

TaskQueue

public boolean force(Runnable o, long timeout, TimeUnit unit) throws InterruptedException {

    if ( parent.isShutdown() )

        throw new RejectedExecutionException(
            "Executor not running, can't force a command into the queue");

    return super.offer(o,timeout,unit); //forces the item onto the queue, to be used if the taskis rejected
    }

connector配置

配置项默认值说明
acceptorThreadCount1acceptor 线程数量
pollerThreadCount1poller 线程数量
minSpareThreads10核心线程数,即 corePoolSize
maxThreads200最大线程数,即 maximumPoolSize
exector-exector名称,用来引用下面的Exector

Exector配置

配置项默认值说明
threadPriority5线程优先级
daemontrue是否守护线程
minSpareThreads25核心线程数,即 corePoolSize
maxThreads200最大线程数,即 maximumPoolSize
maxIdleTime60000线程生存时间,单位是毫秒,默认值为1分钟
maxQueueSizeInteger.MAX_VALUE队列长度
prestartminSpareThreadsfale核心线程是否在服务器启动时启动