线程池的分类

359 阅读4分钟

线程池创建方式

线程池创建通常有两种方式

  1. 手动new ThreadPoolExecutor 根据需求进行配置。
  2. 使用ExecutorService工厂进行配置。

线程池的分类

  1. FixThreadPool

通过ExecutorService的newFixedThreadPool方法来创建。

/**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue, using the provided
     * ThreadFactory to create new threads when needed.  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
     * @param threadFactory the factory to use when creating new threads
     * @return the newly created thread pool
     * @throws NullPointerException if threadFactory is null
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }

注释说的是比较清晰的。这个线程池的线程数量是固定的,核心线程和总的线程数都是核心线程数,那么就说明这个线程池中只有核心线程,那么由于核心线程是一直存活的,那所提交的任务如果小于核心线程数就会立即得到执行,所以响应的速度是比较高的。阻塞队列用的是无界的,如果所有的核心线程都在占用,那么提交的任务全部都会插入到阻塞队列中。

  1. CachedPoolThread

通过ExecutorService的newCachedThreadPool来创建。

 /*
     * 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>());
    }

这个线程池没有核心线程,会按需创建线程,但是会重用处于空闲状态的线程。同时阻塞队列是SynchronousQueue,它无法存储元素,所以提交的任务都会被执行。因为maximumPoolSize为 Integer.MAX_VALUE特别大,所以基本上提交的任务都会立即执行。超时限制为6线程就0s,所以如果60s后如果没有新的任务到来,那么会被terminated,所以如果线程池长时间没有任务,那么所有的线程都会被销毁,那么就不会消耗资源。 CachedPoolThread适用于执行大量耗时较短的任务。

应用场景:Okhttp的网络请求

public final class Dispatcher {

  /** Executes calls. Created lazily. */
  private @Nullable ExecutorService executorService;
  
public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }
}
  1. ScheduledThreadPool

通过ExecutorService的newCachedThreadPool来创建。

    /**
     * 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
     * @param threadFactory the factory to use when the executor
     * creates a new thread
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     * @throws NullPointerException if threadFactory is null
     */
    public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }
    public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue(), threadFactory);
    }

它用于执行定时任务或者周期性任务,有固定的核心线程数,非核心线程数会在超过空闲时间后回收。

应用场景:RxJava中

如在SchedulerPoolFactory.java

public class NewThreadWorker extends Scheduler.Worker implements Disposable {
   private final ScheduledExecutorService executor;


   public NewThreadWorker(ThreadFactory threadFactory) {
       executor = SchedulerPoolFactory.create(threadFactory);
   }
** SchedulerPoolFactory.java**
/**
    * Creates a ScheduledExecutorService with the given factory.
    * @param factory the thread factory
    * @return the ScheduledExecutorService
    */
   public static ScheduledExecutorService create(ThreadFactory factory) {
   ** 注意这里**
       final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, factory);
       tryPutIntoPool(PURGE_ENABLED, exec);
       return exec;
   }
  1. SingleThreadPool

通过ExecutorService的newSingleThreadExecutor来创建。

/**
     * 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>()));
    }

核心线程数为1,最大线程数为1,所以同一时刻只有1个任务运行,阻塞队列为无界队列,按序插入,也只能按序取出执行,所以该线程池实现了任务的顺序执行。因而不需要处理同步问题。