美文网首页工作生活
线程池,使用ThreadPoolExecutor代替Execut

线程池,使用ThreadPoolExecutor代替Execut

作者: 撸完代码送快递 | 来源:发表于2019-07-04 18:17 被阅读0次
    image.png

    合理使用线程池的好处:

    • 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
    • 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
    • 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。但是要做到合理的利用线程池,必须对其原理了如指掌

    Executor架构

    image.png

    在HotSpot虚拟机中,Java中的线程将会被一一映射为操作系统的线程 在Java虚拟机层面,用户将多个任务提交给Executor框架,Executor负责分配线程执行它们; 在操作系统层面,操作系统再将这些线程分配给处理器执行


    image.png

    Executor框架中的所有类可以分成三类:
    1.任务 任务有两种类型:Runnable和Callable。
    2.任务执行器 Executor框架最核心的接口是Executor,它表示任务的执行器。
    Executor的子接口为ExecutorService。
    ExecutorService有两大实现类:ThreadPoolExecutor和ScheduledThreadPoolExecutor。
    3.执行结果
    Future接口表示异步的执行结果,它的实现类为FutureTask。

    ThreadPoolExecutor类

    image.png

    Executor接口

    Executor接口只有一个execute方法,用来替代通常创建或启动线程的方法。

    ExecutorService接口

    ExecutorService接口继承自Executor接口,提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。增加了shutDown(),shutDownNow(),invokeAll(),invokeAny()和submit()等方法。如果需要支持即时关闭,也就是shutDownNow()方法,则任务需要正确处理中断。

    AbstractExecutorService抽象类

    提供ExecutorService接口的默认实现方法。

    创建线程池的方法

    ExecutorService threadPool = new ThreadPoolExecutor(1, 5, 30, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<Runnable>(1024), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
    

    其中线程工厂可以使用guava包中的方法创建:

    ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
    

    参数说明:

    • corePoolSize
      核心线程数,默认情况下核心线程会一直存活,即使处于闲置状态也不会受存keepAliveTime限制。除非将allowCoreThreadTimeOut设置为true。
    • maximumPoolSize
      线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的LinkedBlockingDeque时,这个值无效。
    • keepAliveTime
      非核心线程的闲置超时时间,超过这个时间就会被回收。
    • workQueue
      线程池中的任务队列。常用的有三种队列,SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue。
    • threadFactory
      线程工厂,提供创建新线程的功能。
    • RejectedExecutionHandler
      当线程池中的资源已经全部使用,添加新线程被拒绝时,会调用RejectedExecutionHandler的rejectedExecution方法。

    线程池规则:
    1.如果线程数量<=核心线程数量,那么直接启动一个核心线程来执行任务,不会放入队列中。
    2.如果线程数量>核心线程数,但<=最大线程数,并且任务队列是LinkedBlockingDeque的时候,超过核心线程数量的任务会放在任务队列中排队。
    3.如果线程数量>核心线程数,但<=最大线程数,并且任务队列是SynchronousQueue的时候,线程池会创建新线程执行任务,这些任务也不会被放在任务队列中。这些线程属于非核心线程,在任务完成后,闲置时间达到了超时时间就会被清除。
    4.如果线程数量>核心线程数,并且>最大线程数,当任务队列是LinkedBlockingDeque,会将超过核心线程的任务放在任务队列中排队。也就是当任务队列是LinkedBlockingDeque并且没有大小限制时,线程池的最大线程数设置是无效的,他的线程数最多不会超过核心线程数。
    5.如果线程数量>核心线程数,并且>最大线程数,当任务队列是SynchronousQueue的时候,会因为线程池拒绝添加任务而抛出异常。


    image.png

    使coreThread失效

    之前设置的keepAliveTime参数只能使超过此阈值的非核心线程失效,使用allowCoreThreadTimeOut(boolean value)方法将allowCoreThreadTimeOut设置为true则可以将该策略应用于核心线程。

    http://www.ideabuffer.cn/2017/04/04/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%EF%BC%9AThreadPoolExecutor/
    https://blog.csdn.net/z_s_z2016/article/details/81674893

    相关文章

      网友评论

        本文标题:线程池,使用ThreadPoolExecutor代替Execut

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