首页 > 技术文章 > Java 线程池

ruhuanxingyun 2020-02-12 09:06 原文

1. 池化技术

  A. 程序运行的本质:占用系统资源,CPU/磁盘网络进行使用;

  B. 池有线程池、连接池、内存池、对象池等,因为线程的创建和销毁,数据库的连接和断开都很耗资源;

  C. 池化技术就是提前准备一些资源,以供使用。

2. 线程池作用

  A. 重用存在的线程,减少对象创建、消亡的开销,性能佳;

  B. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞;

  C. 提供定时执行、定期执行、单线程、并发数控制等功能。

3. 线程池创建方式(Executors类)

  A. ExecutorService executorService = Executors.newFixedThreadPool(5):重用指定数目的线程,其背后使用的是无界的工作队列,任何时候最多有nThreads个工作线程是活动的,如果任务数量超过了活动队列数目,将在工作队列中等待空闲线程出现,如果有工作线程退出,将会有新的工作线程被创建,以补足指定的数目nThreads;

  B. ExecutorService executorService = Executors.newCachedThreadPool():它是一种用来处理大量短时间工作任务的线程池,特点是它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程,如果线程闲置的时间超 60秒,则被终止并移出缓存,长时间闲置时,这种线程池,不会消耗什么资源,其内部使用SynchronousQueue作为工作队列;

  C. ExecutorService executorService = Executors.newSingleThreadExecutor():特点在于工作线程数目被限制为1,操作一个无界的工作队列,所以它保证了所有任务的都是被顺序执行,最多会有一个任务处于活动状态,并且不允许使用者改动线程池实例,因此可以避免其改变线程数目;

  D. ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor():创建单线程池,可以进行定时或周期性的工作调度;

  E. ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5):可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程;

  F.  ExecutorService executorService = Executors.newWorkStealingPool():Java 8才加入这个创建方法,其内部会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序;

  G. ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor():是最原始的线程池创建;

  注意:阿里巴巴不允许使用Executors去创建线程池,规避资源耗尽的风险,推荐最后一种。

4. 线程池七大参数

  A. corePoolSize:核心线程的数量;

  B. maximumPoolSize:最大线程的数量;

  C. keepAliveTime:空闲线程保留的时间,默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用;

  D. unit:keepAliveTime的时间单位;

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

  E. workQueue:阻塞队列,用来存储等待执行的任务;

ArrayBlockingQueue   // 基于数组的先进先出队列,此队列创建时必须指定大小
LinkedBlockingQueue  // 基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE
SynchronousQueue     // 这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务

  F. threadFactory:线程工厂,主要用来创建线程;

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

ThreadPoolExecutor.AbortPolicy           // 丢弃任务并抛出RejectedExecutionException异常(默认策略)
ThreadPoolExecutor.DiscardPolicy         // 也是丢弃任务,但是不抛出异常
ThreadPoolExecutor.DiscardOldestPolicy   // 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy      // 由调用线程处理该任务 

5. 线程池的状态

  A. RUNNING:这是最正常的状态,接受新的任务,处理等待队列中的任务;

  B. SHUTDOWN:不接受新的任务提交,但是会继续处理等待队列中的任务;

  C. STOP:不接受新的任务提交,不再处理等待队列中的任务,中断正在执行任务的线程;

  E. TIDYING:所有的任务都销毁了,workCount 为 0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated();

  F. TERMINATED:terminated()方法结束后,线程池的状态就会变成这个。

6. ExecutorService方法

  A. execute():只能执行Runnable类型的任务;

  B. submit():可以执行Runnable和Callable类型的任务;

  C. shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务;

  D. shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。

 7. 线程池工作流程

  A. 当线程池数量小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程;

  B. 当线程池数量达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行;

  C. 当workQueue队列已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务;

  D. 当提交任务数创建的线程超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理;

  E. 当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程;

       F. 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭。

 

推荐阅读