java-线程池(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nanruitao10/article/details/85107331

一、为什么使用线程池

  1. 重用线程池中的使用,减少创建线和销毁程的的资源消耗和提高性能。
  2. 可以对线程进行管理与维护

二、线程池的创建

  线程池的创建可以使用Executors类中的方法创建,可以参考常用的四种线程池的创建,下面来看J.U.C包下的ThreadPoolExecutor,此类主要有以下构造方法:

/**第一种创建方式*/
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,
                              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) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
/**第四种创建方式*/
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.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

corePoolSize:核心线程池的大小,线程池创建完成之后,线程池中默认没有任何线程。只有在有任务到达时才会创建一个线程去执行,直到corePoolSize。

maximumPoolSize:线程池中允许最大的线程数。

keepAliveTime:空闲线程等待新任务的最大存活时间。

unit:keepAliveTime的时间单位,比如TimeUnit.MILLISECONDS;TimeUnit.SECONDS; TimeUnit.MINUTES; TimeUnit.HOURS;

workQueue:阻塞队列,当线程池中的线程大于corePoolSize时,新建的任务将会进入阻塞队列等待执行,可以查看常用的阻塞队列

threadFactory:创建线程的工厂

handler:拒绝任务的处理策略。

拒绝策略:

  1. AbortPolicy:直接丢弃任务并抛出RejectedExecutionException。
  2. CallerRunsPolicy:只要线程池未关闭,就会执行调用者线程中丢弃的任务,这样会降低线程的性能。
  3. DiscardOldestPolicy:丢弃任务队列中时间最长的任务然后尝试提交当前的任务。
  4. DiscardPolicy:丢弃任务,不做任何处理。

线程池处理任务的规则:

  1. 当前线程池中线程的数目<corePoolSize,则每来一个任务,就会创建一个线程来执行
  2. 当前线程池中线程的数目>=corePoolSize,当有任务时,则会尝试添加到阻塞队列中,若添加成功,则会等待空闲线程来将其执行,若添加失败(一般是阻塞队列已满),则会创建新的线程去执行,当然前提是不能maximumPoolSize的数量。
  3. 若当前线程池中的线程数量>maximumPoolSize,则执行任务拒绝策略处理
  4. 当前线程池中的线程数量?corePoolSize时,若某个空闲线程超过keepAliveTime时间,则会被丢弃,直到线程数量小于corePoolSize。一般情况下,核心线程不会被丢弃。

线程池中任务到达的执行流程:

线程池中的状态:

  • RUNNING:接收新的任务,执行任务队列中的任务。
  • SHUTDOWN:不接收新任务,但是执行任务队列中的任务。
  • STOP:不接收新任务,也不执行任务队列中的任务,并打断正在执行的任务。
  • TIDYING:终止所有的任务,工作线程的数量为0,并且会执行terminated()回调函数。
  • TERMINATED:terminated()方法已执行完毕。

状态转换:

RUNNING -> SHUTDOWN: 在调用shutDown()方法时。

(RUNNING or SHUTDOWN) -> STOP:在调用shutDownNow()方法时。

SHUTDOWN -> TIDYING:线程池和阻塞队列都为空。

STOP -> TIDYING :线程池为空。

TIDYING -> TERMINATED :terminated()方法执行完毕时。

猜你喜欢

转载自blog.csdn.net/nanruitao10/article/details/85107331