美文网首页
线程池(三):线程池排队机制

线程池(三):线程池排队机制

作者: bug音音 | 来源:发表于2020-12-08 14:18 被阅读0次

1、为什么JDK1.5引入线程池

在Java中,如果每个任务都创建一个新的thread,开销是非常大的。除了创建和销毁线程的时间开销外,还消耗大量的系统资源。为了规避以上问题,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有的线程对象来进行服务,这就是线程池引入的原因。

2、ThreadPoolExecutor类分析

(a)ThreadPoolExecutor构造函数:

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler);

1)corePoolSize 核心线程数

(2)maximumPoolSize 最大线程数

(3)keepAliveTime 线程被回收前的空闲时间

(4)workQueue 任务队列

(5)threadFactory 线程创建工厂

(6)handler 线程池对拒绝任务的处理策略

(b)ThreadPoolExecutor运行原理:

ThreadPoolExecutor将根据corePoolSize和maximumPoolSize设置的值调整线程池大小。当新任务调用方法execute(Runnable)提交时,如果运行的线程少于corePoolSize,则创建新线程来处理请求。如果正在运行的线程数等于corePoolSize时,则新任务被添加到队列中,直到队列满。当队列满了后,会继续开辟新线程来处理任务,但不超过最大线程数。当任务队列满了并且已开辟了最大线程数,此时又来了新任务,ThreadPoolExecutor会拒绝服务。

(c)keepAliveTime注意事项:

/**

* Timeout in nanoseconds for idle threads waiting for work.

* Threads use this timeout when there are more than corePoolSize

* present or if allowCoreThreadTimeOut. Otherwise they wait

* forever for new work.

*/

private volatile long keepAliveTime;

说明:当线程空闲超过keepAliveTime,非核心线程会被回收,若allowCoreThreadTimeOut为true则核心线程也会被回收。

/**

* If false (default), core threads stay alive even when idle.

* If true, core threads use keepAliveTime to time out waiting

* for work.

*/

private volatile boolean allowCoreThreadTimeOut;

说明:默认情况下,核心线程不会被回收;当allowCoreThreadTimeOut为true,核心线程也会被回收。

3、任务队列

BlockingQueue<Runnable> workQueue;

workQueue是一个BlockingQueue接口的对象,仅用于存放Runnable对象。

(1)直接提交(如SynchronousQueue)

直接提交策略表示线程池不对任务进行缓存。新进任务直接提交给线程池,当线程池中没有空闲线程时,创建一个新的线程处理此任务。这种策略需要线程池具有无限增长的可能性。

Executors.newCachedThreadPool()使用SynchronousQueue创建线程池。

(2)无界队列(如不具有预定义容量的LinkedBlockingQueue)

LinkedBlockingQueue将导致当所有 corePoolSize 线程都忙时新任务在队列中等待。这样,创建的线程就不会超过 corePoolSize。(因此,maximumPoolSize 的值也就无效了。)当每个任务完全独立于其他任务,即任务执行互不影响时,适合于使用无界队列。

Executors.newFixedThreadPool(3)使用LinkedBlockingQueue创建线程池。

Executors.newSingleThreadExecutor()使用LinkedBlockingQueue创建线程池。

(3)有界队列(如ArrayBlockingQueue)

有界队列(如ArrayBlockingQueue)有助于防止资源耗尽当最大线程数有限时,但是可能较难调整和控制。队列大小和最大池大小可能需要相互折衷。

(4)优先级队列(如PriorityBlockingQueue)

(5)DelayedWorkQueue

DelayedWorkQueue是ScheduledThreadPoolExecutor的静态内部类。

Executors.newScheduledThreadPool(3)使用DelayedWorkQueue创建线程池。

4、拒绝策略

接口RejectedExecutionHandler提供了拒绝任务处理的自定义方法的机会。在ThreadPoolExecutor中已经包含四种拒绝策略。

(1)AbortPolicy

拒绝策略:抛出运行时异常RejectedExecutionException。

这种策略丢弃任务,并抛出异常。(jdk默认策略)

(2)DiscardPolicy

拒绝策略:不能执行的任务将被丢弃。

这种策略什么都没做。

(3)DiscardOldestPolicy

拒绝策略:如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序。

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

    if (!e.isShutdown()) {

        e.getQueue().poll();

        e.execute(r);

    }

}

该策略稍微复杂一些,在pool没有关闭的前提下首先丢掉缓存在队列中的最早的任务,然后重新尝试运行该任务。

(4)CallerRunsPolicy

拒绝策略:线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

    if (!e.isShutdown()) {

        r.run();

    }

}

这个策略不想放弃执行任务。但是由于池中已经没有任何资源了,那么就直接使用调用该execute的线程本身来执行。

相关文章

  • 线程池(三):线程池排队机制

    1、为什么JDK1.5引入线程池 在Java中,如果每个任务都创建一个新的thread,开销是非常大的。除了创建和...

  • 多线程juc线程池

    java_basic juc线程池 创建线程池 handler是线程池拒绝策略 排队策略 线程池状态 RUNNIN...

  • 线程池

    线程池解决的核心问题:资源管理问题。 线程池运行机制最主要的三个点: 线程池如何维护自身状态; 线程池如何管理任务...

  • 线程池工作机制与原理

    书接上文, Java线程池 。接下来记录一下线程池的工作机制和原理 线程池的两个核心队列: 线程等待池,即线程队列...

  • 20.多线程总结(七)-ThreadPoolExecutor线程

    1.如何创建一个线程池? 2.线程池运行机制 a.new线程池时,线程池工作队列中已经被添加的Runnable是否...

  • java线程池

    线程VS线程池 普通线程使用 创建线程池 执行任务 执行完毕,释放线程对象 线程池 创建线程池 拿线程池线程去执行...

  • AsyncTask的使用及其原理

    概述 Android 已封装好的轻量级异步类。内置一个线程池用于异步任务,另一个线程池用于排队(实际不是线程池)。...

  • 干货,阿里P8浅谈对java线程池的理解(面试必备)

    线程池的概念 线程池由任务队列和工作线程组成,它可以重用线程来避免线程创建的开销,在任务过多时通过排队避免创建过多...

  • 线程池

    一 线程池简介 线程池由任务队列和工作线程组成,它可以重用线程来避免线程创建的开销,在任务过多时通过排队避免创建过...

  • 线程池查漏补缺

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

网友评论

      本文标题:线程池(三):线程池排队机制

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