zoukankan      html  css  js  c++  java
  • 线程池ThreadPoolExecutor

    线程池ThreadPoolExecutor


    为什么要使用线程池

    我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:

    如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。

    那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?

    在Java中可以通过线程池来达到这样的效果。

    ThreadPoolExecutor 继承了 AbstractExecutorService抽象类
    AbstractExecutorService 继承了 ExecutorService 接口
    ExecutorService 继承了 Executor 接口
    

    线程 有五种状态:新建,就绪,运行,阻塞,死亡,线程池也有五种状态。

    线程池的五种状态

    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;
    

    RUNNING:处于RUNNING状态的线程池能够接受新任务,以及对新添加的任务进行处理。

    SHUTDOWN:处于SHUTDOWN状态的线程池不可以接受新任务,但是可以对已添加的任务进行处理。

    STOP:处于STOP状态的线程池不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。

    TIDYING:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。

    TERMINATED:线程池彻底终止的状态。

    构造函数

    1.corePoolSize 核心线程池的大小。当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;
    
    2.maximumPoolSize 线程池允许的最大线程数量,线程池的阻塞队列满了之后,如果还有任务提交,如果当前的线程数小于maximumPoolSize,则会新建线程来执行任务。注意,如果使用的是无界队列,该参数也就没有什么效果了。
    
    3.keepAliveTime 当线程的数量大于核心线程池中规定的数量,空闲的线程允许存活的时间。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize
    
    4.unit 参数keepAliveTime的时间单位
    
    5.workQueue 阻塞队列
    
    6.threadFactory 线程工厂,主要用来创建线程;
    
    7.handler 表示当拒绝处理任务时的策略,所谓拒绝策略,是指将任务添加到线程池中时,线程池拒绝该任务所采取的相应策略。当向线程池中提交任务时,如果此时线程池中的线程已经饱和了,而且阻塞队列也已经满了,则线程池会选择一种拒绝策略来处理该任务。有以下四种取值:
    ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 
    ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 
    ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
    ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
    
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
    
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
    
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler) {
            if (corePoolSize < 0 ||
                maximumPoolSize <= 0 ||
                maximumPoolSize < corePoolSize ||
                keepAliveTime < 0)
                throw new IllegalArgumentException();
            if (workQueue == null || threadFactory == null || handler == null)
                throw new NullPointerException();
            this.acc = System.getSecurityManager() == null ?
                    null :
                    AccessController.getContext();
            this.corePoolSize = corePoolSize;
            this.maximumPoolSize = maximumPoolSize;
            this.workQueue = workQueue;
            this.keepAliveTime = unit.toNanos(keepAliveTime);
            this.threadFactory = threadFactory;
            this.handler = handler;
        }
    

    Executor框架提供了三种线程池,他们都可以通过工具类Executors来创建。

    1.FixedThreadPool,可重用固定线程数的线程池,其定义如下:

     public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }
    

    2.SingleThreadExecutor是使用单个worker线程的Executor,定义如下:

     public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
    

    CachedThreadPool是一个会根据需要创建新线程的线程池 ,他定义如下:

    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
        }
    

    任务提交

    线程池根据业务不同的需求提供了两种方式提交任务:Executor.execute()、ExecutorService.submit()。其中ExecutorService.submit()可以获取该任务执行的Future。

    任务终止

    线程池ThreadPoolExecutor提供了shutdown()和shutDownNow()用于关闭线程池。

    shutdown():按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。

    shutdownNow() :尝试停止所有的活动执行任务、暂停等待任务的处理,并返回等待执行的任务列表。


    参考资料:

    http://cmsblogs.com/?p=2448

    https://www.cnblogs.com/dolphin0520/p/3932921.html

  • 相关阅读:
    linux系统根目录文件系统空间不足导致的错误
    python---对象
    公共函数
    PHP接口(interface)和抽象类(abstract)
    mysql引擎
    InstallShield自定义图片资源
    InstallShield 创建自己的Dialog
    InstallShield:自己备份
    注册表和ODBC
    IS脚本学习
  • 原文地址:https://www.cnblogs.com/fruitknife/p/9703178.html
Copyright © 2011-2022 走看看