线程池

线程池

项目文件:HelloJava-ThreadPoolExecutorDemo

  1. 线程池优点:

    • 重用线程,避免创建和销毁线程的性能开销;
    • 有效控制线程池最大并发数,避免大量线程之间因互相抢占系统资源而导致的阻塞现象;
    • 能对线程进行简单管理,并提供定时执行已经间隔循环执行等功能;
  2. 继承关系:源于Executor;真正实现是ThreadPoolExecotor;

    public interface Executor {
        void execute(Runnable command);
    }
    public interface ExecutorService extends Executor {...}
    public abstract class AbstractExecutorService implements ExecutorService {...}
    public class ThreadPoolExecutor extends AbstractExecutorService {...}
    
  3. ThreadPoolExecutor

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue
                              ThreadFactory threadFactory
                              RejectedExecutionHandler handler){
        ...
        private volatile boolean allowCoreThreadTimeOut;
        ...
    }
    
    • corePoolSize:核心线程数,核心线程会在线程池中一直存活。如果allowCoreThreadTimeOut为true,闲置的核心线程等待时长超过keepAliveTIme所指定的时长,核心线程会被终止;

    • maximumPoolSize:线程池所能容纳的最大线程数;

    • keepAliveTime非核心线程闲置的超时时长,超过时长,非核心线程被回收;如果allowCoreThreadTimeOut为true,同样作用于核心线程;

    • unit: keepAliveTime参数的时间单位,枚举值,常用TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS、TimeUnit.MINUTES;

    • workQueue:任务队列,通过线程execute方法提交的Runnable对象会存储在这个参数中;

    • threadFactory:线程工厂,为线程池提供创建新线程的功能。

      public interface ThreadFactory {
          Thread newThread(Runnable r);
      }
      
    • RejectedExecutionHandler handler:当线程池无法执行新任务,如任务队列已满或者无法成功执行任务,会调用handler.rejectedExecution,默认抛出异常。

  4. ThreadPoolExecutor执行流程:

    • 先开核心线程
    • 填充任务队列
    • 任务队列满了但未达到maximumPoolSize,再开非核心线程
    • 线程池数量达到线程池规定的最大值maximumPoolSize,handler抛出异常;
  5. 线程池分类:

    • FixedThreadPool:线程数量固定,只有核心线程且不会被回收;任务队列没有大小限制;

       public static ExecutorService newFixedThreadPool(int nThreads) {
           return new ThreadPoolExecutor(nThreads, nThreads,
                                         0L, TimeUnit.MILLISECONDS,
                                         new LinkedBlockingQueue());
       }
      
    • CachedThreadPool:只有非核心线程,线程数量不定;超时60s回收;SynchronousQueue可以理解为无法存储元素的队列;适合执行大量的耗时少的任务,当线程池闲置时,线程都会被超时回收,几乎不占用系统资源;

      public static ExecutorService newCachedThreadPool() {
          return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                        60L, TimeUnit.SECONDS,
                                        new SynchronousQueue());
      }
      
    • ScheduledThreadPool:核心线程固定,非核心线程没有限制,非核心线程闲置立即回收(keepAliveTime为0);主要执行定时任务周期任务;schedule:计划(表),进度表,调度。

      public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
          return new ScheduledThreadPoolExecutor(corePoolSize);
      }
      
      public ScheduledThreadPoolExecutor(int corePoolSize) {
          super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
                new DelayedWorkQueue());
      }
      
    • SingleThreadPool只有一个核心线程;所有任务统一到一个线程,不需要处理线程同步问题。

      public static ExecutorService newSingleThreadExecutor() {
          return new FinalizableDelegatedExecutorService
              (new ThreadPoolExecutor(1, 1,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue()));
      }
      
  6. 通过Executors来创建线程池;(非Executor)

    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
    fixedThreadPool.execute(runnable);
    
    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    cachedThreadPool.execute(runnable);
    
    ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4);
    scheduledThreadPool.execute(runnable);
    
    ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
    singleThreadExecutor.execute(runnable);
    

你可能感兴趣的:(线程池)