线程池详解

在Android开发中,有时会遇到需要新开线程,比如操作本地数据库,比如Application中初始化耗时的方法,比如请求网络等等,直接使用Thread操作,对程序的性能和维护上都是一个问题。使用Java提供的线程池来操作可以很好的解决问题。

 

Java本身 提供 通过工厂类Executors创建几种类型的线程池。

 

 

 

 

一.工厂类Executors创建线程池

 

1.newCachedThreadPool

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

 

代码

ExecutorService executorService= Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
     @Override
     public void run() {
                
     }
});

 

源码

/**
 * Creates a thread pool that creates new threads as needed, but
 * will reuse previously constructed threads when they are
 * available.  These pools will typically improve the performance
 * of programs that execute many short-lived asynchronous tasks.
 * Calls to {@code execute} will reuse previously constructed
 * threads if available. If no existing thread is available, a new
 * thread will be created and added to the pool. Threads that have
 * not been used for sixty seconds are terminated and removed from
 * the cache. Thus, a pool that remains idle for long enough will
 * not consume any resources. Note that pools with similar
 * properties but different details (for example, timeout parameters)
 * may be created using {@link ThreadPoolExecutor} constructors.
 *
 * @return the newly created thread pool
 */
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

 

详解

使用 工厂类Executors的 newCachedThreadPool()方法创建线程 实际  调用ThreadPoolExecutor类创建线程。返回ExecutorService 实例。

参数 corePoolSize:0。

参数 maximumPoolSize:Integer.MAX_VALUE。

参数 keepAliveTime:60L。

参数 unit:TimeUnit.SECONDS。

参数 workQueue:SynchronousQueue(同步队列)。

当有新任务到来,则插入到SynchronousQueue中,由于SynchronousQueue是同步队列,因此会在池中寻找可用线程来执行,若有可以线程则执行,若没有可用线程则创建一个线程来执行该任务;若池中线程空闲时间超过指定大小,则该线程会被销毁。

适用于执行很多短期异步的小程序或者负载较轻的服务器。

 

 

 

 

2.newFixedThreadPool

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

 

代码

ExecutorService executorService= Executors.newFixedThreadPool(5);
executorService.execute(new Runnable() {
     @Override
     public void run() {

     }
});

 

源码

/**
 * Creates a thread pool that reuses a fixed number of threads
 * operating off a shared unbounded queue.  At any point, at most
 * {@code nThreads} threads will be active processing tasks.
 * If additional tasks are submitted when all threads are active,
 * they will wait in the queue until a thread is available.
 * If any thread terminates due to a failure during execution
 * prior to shutdown, a new one will take its place if needed to
 * execute subsequent tasks.  The threads in the pool will exist
 * until it is explicitly {@link ExecutorService#shutdown shutdown}.
 *
 * @param nThreads the number of threads in the pool
 * @return the newly created thread pool
 * @throws IllegalArgumentException if {@code nThreads <= 0}
 */
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

 

详解

使用 工厂类Executors的 newFixedThreadPool()方法创建线程 实际  调用ThreadPoolExecutor类创建线程。返回ExecutorService 实例。

参数 corePoolSize:所设定线程数量nThread。

参数 maximumPoolSize:所设定线程数量nThread。

参数 keepAliveTime:0L(不限时)。

参数 unit:TimeUnit.MILLISECONDS。

参数 workQueue:LinkedBlockingQueue(无界阻塞队列)。

创建可容纳固定数量线程的池子,每隔线程的存活时间是无限的,当池子满了就不在添加线程了;如果池中的所有线程均在繁忙状态,对于新任务会进入阻塞队列中(无界的阻塞队列)。

适用于执行长期的任务,性能好很多。

 

 

 

3.newScheduledThreadPool

创建一个定长线程池,支持定时及周期性任务执行。

 

代码

ExecutorService executorService= Executors.newScheduledThreadPool(5);
executorService.execute(new Runnable() {
   @Override
   public void run() {

   }
});

 

源码

/**
 * Creates a thread pool that can schedule commands to run after a
 * given delay, or to execute periodically.
 * @param corePoolSize the number of threads to keep in the pool,
 * even if they are idle
 * @return a newly created scheduled thread pool
 * @throws IllegalArgumentException if {@code corePoolSize < 0}
 */
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}
 /**
 * Creates a new {@code ScheduledThreadPoolExecutor} with the
 * given core pool size.
 *
 * @param corePoolSize the number of threads to keep in the pool, even
 *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
 * @throws IllegalArgumentException if {@code corePoolSize < 0}
 */
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE,
          DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
          new DelayedWorkQueue());
}

点击super

/**
 * Creates a new {@code ThreadPoolExecutor} with the given initial
 * parameters and default thread factory and rejected execution handler.
 * It may be more convenient to use one of the {@link Executors} factory
 * methods instead of this general purpose constructor.
 *
 * @param corePoolSize the number of threads to keep in the pool, even
 *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
 * @param maximumPoolSize the maximum number of threads to allow in the
 *        pool
 * @param keepAliveTime when the number of threads is greater than
 *        the core, this is the maximum time that excess idle threads
 *        will wait for new tasks before terminating.
 * @param unit the time unit for the {@code keepAliveTime} argument
 * @param workQueue the queue to use for holding tasks before they are
 *        executed.  This queue will hold only the {@code Runnable}
 *        tasks submitted by the {@code execute} method.
 * @throws IllegalArgumentException if one of the following holds:<br>
 *         {@code corePoolSize < 0}<br>
 *         {@code keepAliveTime < 0}<br>
 *         {@code maximumPoolSize <= 0}<br>
 *         {@code maximumPoolSize < corePoolSize}
 * @throws NullPointerException if {@code workQueue} is null
 */
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
        Executors.defaultThreadFactory(), defaultHandler);
}

 

 

详解

使用 工厂类Executors的 newScheduledThreadPool()方法创建线程 实际  调用ThreadPoolExecutor类创建线程。返回ExecutorService 实例。

参数 corePoolSize:传递来的参数。

参数 maximumPoolSize:Integer.MAX_VALUE。

参数 keepAliveTime:10L。

参数 unit:TimeUnit.MILLISECONDS。

参数 workQueue:DelayedWorkQueue(一个按超时时间升序排序的队列)。

创建一个固定大小的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序的队列结构。

适用于周期性执行任务的场景。

 

 

 

4.newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

 

代码

ExecutorService executorService= Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
    @Override
    public void run() {

    }
});

 

源码

/**
 * Creates an Executor that uses a single worker thread operating
 * off an unbounded queue. (Note however that if this single
 * thread terminates due to a failure during execution prior to
 * shutdown, a new one will take its place if needed to execute
 * subsequent tasks.)  Tasks are guaranteed to execute
 * sequentially, and no more than one task will be active at any
 * given time. Unlike the otherwise equivalent
 * {@code newFixedThreadPool(1)} the returned executor is
 * guaranteed not to be reconfigurable to use additional threads.
 *
 * @return the newly created single-threaded Executor
 */
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

 

详解

使用 工厂类Executors的 newSingleThreadExecutor()方法创建线程 实际  调用ThreadPoolExecutor类创建线程。返回ExecutorService 实例。

参数 corePoolSize:1。

参数 maximumPoolSize:1。

参数 keepAliveTime:0L(不限时)。

参数 unit:TimeUnit.MILLISECONDS。

参数 workQueue:LinkedBlockingQueue(无界阻塞队列)。

创建只有一个线程的线程池,且线程的存活时间是无限的;当该线程正繁忙时,对于新任务会进入阻塞队列中(无界的阻塞队列)。

适用于一个任务一个任务执行的场景。

 

 

综上Java本身提供的通过工厂类Executors创建几种类型的线程池。源码都是通过ThreadPoolExecutor类创建ExecutorService对象。只不过是默认传了一些参数。所以下面我们讲解一下ThreadPoolExecutor类

 

 

 

 

 

 

 

 

 

二.ThreadPoolExecutor类详解

 

ThreadPoolExecutor类是线程池最核心的一个类,因此如果要透彻地了解Java中的线程池,必须先了解这个类。下面我们来看一下ThreadPoolExecutor类的具体实现源码。

 

ThreadPoolExecutor类继承AbstractExecutorService抽象类

public class ThreadPoolExecutor extends AbstractExecutorService

 

ThreadPoolExecutor类有多个构造方法

 

构造方法

/**
 * Creates a new {@code ThreadPoolExecutor} with the given initial
 * parameters and default thread factory and rejected execution handler.
 * It may be more convenient to use one of the {@link Executors} factory
 * methods instead of this general purpose constructor.
 *
 * @param corePoolSize the number of threads to keep in the pool, even
 *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
 * @param maximumPoolSize the maximum number of threads to allow in the
 *        pool
 * @param keepAliveTime when the number of threads is greater than
 *        the core, this is the maximum time that excess idle threads
 *        will wait for new tasks before terminating.
 * @param unit the time unit for the {@code keepAliveTime} argument
 * @param workQueue the queue to use for holding tasks before they are
 *        executed.  This queue will hold only the {@code Runnable}
 *        tasks submitted by the {@code execute} method.
 * @throws IllegalArgumentException if one of the following holds:<br>
 *         {@code corePoolSize < 0}<br>
 *         {@code keepAliveTime < 0}<br>
 *         {@code maximumPoolSize <= 0}<br>
 *         {@code maximumPoolSize < corePoolSize}
 * @throws NullPointerException if {@code workQueue} is null
 */
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

 

 

构造方法

/**
 * Creates a new {@code ThreadPoolExecutor} with the given initial
 * parameters and default rejected execution handler.
 *
 * @param corePoolSize the number of threads to keep in the pool, even
 *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
 * @param maximumPoolSize the maximum number of threads to allow in the
 *        pool
 * @param keepAliveTime when the number of threads is greater than
 *        the core, this is the maximum time that excess idle threads
 *        will wait for new tasks before terminating.
 * @param unit the time unit for the {@code keepAliveTime} argument
 * @param workQueue the queue to use for holding tasks before they are
 *        executed.  This queue will hold only the {@code Runnable}
 *        tasks submitted by the {@code execute} method.
 * @param threadFactory the factory to use when the executor
 *        creates a new thread
 * @throws IllegalArgumentException if one of the following holds:<br>
 *         {@code corePoolSize < 0}<br>
 *         {@code keepAliveTime < 0}<br>
 *         {@code maximumPoolSize <= 0}<br>
 *         {@code maximumPoolSize < corePoolSize}
 * @throws NullPointerException if {@code workQueue}
 *         or {@code threadFactory} is null
 */
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         threadFactory, defaultHandler);
}

 

 

构造方法

/**
 * Creates a new {@code ThreadPoolExecutor} with the given initial
 * parameters and default thread factory.
 *
 * @param corePoolSize the number of threads to keep in the pool, even
 *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
 * @param maximumPoolSize the maximum number of threads to allow in the
 *        pool
 * @param keepAliveTime when the number of threads is greater than
 *        the core, this is the maximum time that excess idle threads
 *        will wait for new tasks before terminating.
 * @param unit the time unit for the {@code keepAliveTime} argument
 * @param workQueue the queue to use for holding tasks before they are
 *        executed.  This queue will hold only the {@code Runnable}
 *        tasks submitted by the {@code execute} method.
 * @param handler the handler to use when execution is blocked
 *        because the thread bounds and queue capacities are reached
 * @throws IllegalArgumentException if one of the following holds:<br>
 *         {@code corePoolSize < 0}<br>
 *         {@code keepAliveTime < 0}<br>
 *         {@code maximumPoolSize <= 0}<br>
 *         {@code maximumPoolSize < corePoolSize}
 * @throws NullPointerException if {@code workQueue}
 *         or {@code handler} is null
 */
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          RejectedExecutionHandler handler) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), handler);
}

 

 

构造方法

/**
 * Creates a new {@code ThreadPoolExecutor} with the given initial
 * parameters.
 *
 * @param corePoolSize the number of threads to keep in the pool, even
 *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
 * @param maximumPoolSize the maximum number of threads to allow in the
 *        pool
 * @param keepAliveTime when the number of threads is greater than
 *        the core, this is the maximum time that excess idle threads
 *        will wait for new tasks before terminating.
 * @param unit the time unit for the {@code keepAliveTime} argument
 * @param workQueue the queue to use for holding tasks before they are
 *        executed.  This queue will hold only the {@code Runnable}
 *        tasks submitted by the {@code execute} method.
 * @param threadFactory the factory to use when the executor
 *        creates a new thread
 * @param handler the handler to use when execution is blocked
 *        because the thread bounds and queue capacities are reached
 * @throws IllegalArgumentException if one of the following holds:<br>
 *         {@code corePoolSize < 0}<br>
 *         {@code keepAliveTime < 0}<br>
 *         {@code maximumPoolSize <= 0}<br>
 *         {@code maximumPoolSize < corePoolSize}
 * @throws NullPointerException if {@code workQueue}
 *         or {@code threadFactory} or {@code handler} is null
 */
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;
}

 

由上可知,ThreadPoolExecutor类共有四个构造方法。但是最后都会执行到七个参数的构造方法。

 

参数详解:

 

<1> corePoolSize

核心线程的大小,在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来创建线程去执行任务。除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,从这2个方法的名字就可以看出,是预创建线程的意思,即在没有任务到来之前就创建corePoolSize个线程或者一个线程。

默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。

有任务要执行时,如果核心线程没有被占用,会优先用核心线程执行任务。

 

 

<2> maximumPoolSize

线程池中允许的最大线程数,这个参数也是一个非常重要的参数,它表示在线程池中最多能创建多少个线程。如果队列满了,并且已创建线程数小于最大线程数,则线程池会再创建新的线程执行任务。所以只有队列满了的时候,这个参数才有意义。

线程总数=核心线程数+非核心线程数。

非核心线程:简单理解,即核心线程都被占用,但还有任务要做,就创建非核心线程。

 

 

<3> keepAliveTime

线程保持存活的时间。表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用。

当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。

如果任务很多,并且每个任务执行的时间比较短,可以调大时间,提高线程的利用率,不然线程刚执行完一个任务,还没来得及处理下一个任务,线程就被终止,而需要线程的时候又再次创建,刚创建完不久执行任务后,没多少时间又终止,会导致资源浪费。

但是如果调用了allowCoreThreadTimeOut(true)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0。

 

 

<4> TimeUnit

参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:

TimeUnit.DAYS;               //天
TimeUnit.HOURS;             //小时
TimeUnit.MINUTES;           //分钟
TimeUnit.SECONDS;           //秒
TimeUnit.MILLISECONDS;      //毫秒
TimeUnit.MICROSECONDS;      //微妙
TimeUnit.NANOSECONDS;       //纳秒

 

 

<5> workQueue

线程池中的任务队列。默认情况下,任务进来之后先分配给核心线程执行,核心线程如果都被占用,并不会立刻开启非核心线程执行任务,而是将任务插入任务队列等待执行,核心线程会从任务队列取任务来执行,任务队列可以设置最大值,一旦插入的任务足够多,达到最大值才会创建非核心线程执行任务。

这个参数的选择也很重要,会对线程池的运行过程产生重大影响,一般来说,这里的阻塞队列有以下几种选择:

 

   (1) SynchronousQueue:这个队列接收到任务的时候,会直接提交给线程处理,而不保留它,如果所有线程都在工作就新建一个线程来处理这个任务。所以为了保证不出现<线程数达到了maximumPoolSize而不能新建线程>的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大。

   (2) LinkedBlockingQueue:这个队列接收到任务的时候,如果当前已经创建的核心线程数小于线程池的核心线程数上限,则新建线程(核心线程)处理任务;如果当前已经创建的核心线程数等于核心线程数上限,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize

   (3) ArrayBlockingQueue:可以限定队列的长度,接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误,或是执行实现定义好的饱和策略。

   (4) DelayQueue:队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务。

 

 

 

<6> threadFactory

线程工厂,主要用来创建线程。可以用线程工厂给每个创建出来的线程设置名字。一般情况下无须设置该参数。

 

 

<7> RejectedExecutionHandler

表示当拒绝处理任务时的策略

这是当任务队列线程池满了时所采取的应对策略,默认是AbordPolicy, 表示无法处理新任务,并抛出 RejectedExecutionException 异常。此外还有3种策略,它们分别如下。

  (1)CallerRunsPolicy:用调用者所在的线程来处理任务。即由调用 execute方法的线程执行该任务。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
(2)DiscardPolicy:不能执行的任务,并将该任务删除且不抛出异常。
(3)DiscardOldestPolicy:丢弃队列最近的任务并执行当前的任务

 

 
综上:
 
(1) 线程数量未达到 corePoolSize,则新建一个线程(核心线程)执行任务。

(2) 线程数量达到了 corePoolSize,则将任务移入队列等待。
 
(3) 队列已满,新建线程(非核心线程)执行任务。

(4) 队列已满,总线程数又达到了 maximumPoolSize,就会由拒绝策略来决定后续的处理。

 

 

 

 

 

 

 

三.ThreadPoolExecutor类常用方法详解

 

一个线程池可以接受任务类型有RunnableCallable,分别对应了execute()方法submit()方法

 

 

<1> execute()方法

execute()方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行。由于execute方法没有返回值,所以说我们也就无法判定任务是否被线程池执行成功。

ExecutorService service = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(128));
service.execute(new Runnable() {
      @Override
      public void run() {
                
      }
});

 

 

<2> submit()方法

submit()方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果。

ExecutorService service = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(128));
Future<Integer> future = service.submit(new Callable<Integer>() {

     @Override
     public Integer call() throws Exception {
            System.out.println("submit方式");
            return 2;
     }
});
     try {
          Integer number = future.get();
     } catch (ExecutionException e) {
          e.printStackTrace();
     } catch (InterruptedException e) {
          e.printStackTrace();
     }

 

 

<3> shutdown()方法

该方法来关闭线程池。

如果调用了shutdown()方法,则线程池处于SHUTDOWN状态,此时线程池不能够接受新的任务,它会等待所有任务执行完毕。

 

 

 

<4> shutdownNow()方法

该方法来关闭线程池。

如果调用了shutdownNow()方法,则线程池处于STOP状态,此时线程池不能接受新的任务,并且会去尝试终止正在执行的任务。

 

 

当线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态。

 

 

 

 

 

 

四.ThreadPoolExecutor简单使用

 

工具类

package com.example.rxjava20.threadpool;

import android.util.Log;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolUtils {

    /**
     * 线程对象
     */

    private static final Executor THREAD_POOL_EXECUTOR;

    /**
     * CPU核数
     */

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

    /**
     * 核心线程大小
     */

    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 3));

    /**
     * 线程池最大线程数
     */

    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT;

    /**
     * 非核心线程闲置超时时长
     */

    private static final int KEEP_ALIVE_SECONDS = 30;

    /**
     * 线程工厂
     */

    private static final ThreadFactory THREAD_FACTORY = new ThreadFactory() {

        private final AtomicInteger mCount = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "ThreadPoolUtils_ThreadName_" + mCount.getAndIncrement());
        }
    };

    /**
     * 线程池中的任务队列
     */

    private static final BlockingQueue<Runnable> POOL_WORK_QUEUE = new LinkedBlockingQueue<Runnable>(128);

    /**
     * 拒绝处理任务时的策略
     */

    private static final RejectedExecutionHandler REJECTED_EXECUTION_HANDLER = new ThreadPoolExecutor.DiscardOldestPolicy() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            super.rejectedExecution(r, e);
        }
    };

    /**
     * 静态代码块 初始化ThreadPoolExecutor
     * */

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                POOL_WORK_QUEUE, THREAD_FACTORY, REJECTED_EXECUTION_HANDLER);
        threadPoolExecutor.allowCoreThreadTimeOut(true);//使keepAliveTime参数起作用
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }

    /**
     * 外部调用
     */

    public static void execute(Runnable runnable) {
        THREAD_POOL_EXECUTOR.execute(runnable);

        Log.d("ThreadPoolUtils", "新开线程CPU_COUNT----:" + CPU_COUNT);
        Log.d("ThreadPoolUtils", "新开线程CORE_POOL_SIZE----:" + CORE_POOL_SIZE);
        Log.d("ThreadPoolUtils", "新开线程MAXIMUM_POOL_SIZE----:" + MAXIMUM_POOL_SIZE);
    }

}

 

 

调用

ThreadPoolUtils.execute(new Runnable() {
   @Override
   public void run() {
       Log.d("ThreadPoolUtils", "新线程执行...." + Thread.currentThread().getName());
   }
});

 

 

 

 

 

 

 

五.总结

 

<1> 线程池的好处

(1) 降低资源消耗。线程池就是通过复用池中的对象,降低系统资源消耗。通过线程池我们可以做到复用线程,任务有多个,但执行任务的线程可以通过线程池来复用,这样减少了创建线程的开销,系统资源利用率得到了提升。

 

(2) 降低管理线程的难度。多线程环境下对线程的管理是最容易出现问题的,而线程池通过框架为我们降低了管理线程的难度。我们不用再去担心何时该销毁线程,如何最大限度的避免多线程的资源竞争。这些事情线程池都帮我们代劳了。

 

(3) 提升任务处理速度。线程池中长期驻留了一定数量的活线程,当任务需要执行时,我们不必先去创建线程,线程池会自己选择利用现有的活线程来处理任务。

 

 

<2>总结

 

当有新任务来的时候,首先要看当前的线程数有没有超过核心线程数,如果没超过直接新建一个线程来执行新的任务,如果超过了就看看缓存队列有没有满,没满就将新任务放进缓存队列中,满了就新建一个线程来执行新的任务,如果线程池中的线程数已经达到了指定的最大线程数了,那就根据相应的策略拒绝任务。

 

当缓存队列中的任务都执行完了的时候,线程池中的线程数如果大于核心线程数,就销毁多出来的线程,直到线程池中的线程数等于核心线程数。此时这些线程就不会被销毁了,它们一直处于阻塞状态,等待新的任务到来。

 

注意: “核心线程”、“非核心线程”是一个虚拟的概念,是为了方便描述而虚拟出来的概念,在代码中并没有哪个线程被标记为“核心线程”或“非核心线程”,所有线程都是一样的,只是当线程池中的线程多于指定的核心线程数量时,会将多出来的线程销毁掉,池中只保留指定个数的线程。那些被销毁的线程是随机的,可能是第一个创建的线程,也可能是最后一个创建的线程,或其它时候创建的线程。一开始我以为会有一些线程被标记为“核心线程”,而其它的则是“非核心线程”,在销毁多余线程的时候只销毁那些“非核心线程”,而“核心线程”不被销毁。这种理解是错误的。

 

FixedThreadPool是一个优秀的线程池,使用时需要注意当线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源;CachedThreadPool线程池,当没有任务执行时,会释放调,当有任务时,又要创建,需要消耗系统开销,而且在大量并发执行时,需要注意控制任务量,避免大量高并发导致系统问题。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值