线程池的原理分析

1.为什么要创建线程池?

  为了避免频繁创建线程对系统的资源开销

  通过控制线程池的线程大小来从而达到限流的效果

2.快速构建线程池

ExecutorService executorService1=Executors.newSingleThreadExecutor();
ExecutorService executorService2=Executors.newFixedThreadPool(2);
ExecutorService executorService3=Executors.newCachedThreadPool();
ExecutorService executorService4=Executors.newScheduledThreadPool();

 

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L,TimeUnit.SECONDS,
      new SynchronousQueue<Runnable>());
    }
  public ThreadPoolExecutor(int corePoolSize,//核心线程数
                              int maximumPoolSize,//最大线程数
                              long keepAliveTime,//非核心空余线程存活时间
                              TimeUnit unit,//存活单位
                              BlockingQueue<Runnable> workQueue//阻塞队列) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory()//构建线程工厂, defaultHandler//拒绝策略);
    }

 

3.线程池的实现原理

线程池判断核心线程里的是否都在执行任务。如果没有执行,则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入如下流程.

线程池判断工作队列是否已满。如果工作队列没有满,会将新提交的任务存储在工作队列中。如果工作队列满了,会进入如下流程。

线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已满了,则交给饱和策略来处理这个任务。

 

 

 

RejectExecutionHandler拒绝策略,当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理新提交的任务,这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常,在JDK1.5中Java线程池框架提供了以下四种策略。

  AbortPolicy:直接抛出异常

  CallerRunsPolicy:只用调用者所在的线程来运行任务

  DiscardOldestPolicy:丢掉队列里最近的一个任务,并执行当前任务

  DiscardPolicy:不处理,丢弃掉

根据业务场景实现RejectExecutionHandler接口自定义策略,如记录日志或持久化存储不能处理的任务

 合理配置线程池

从以下角度分析任务特性
任务的性质:CPU密集型任务,IO密集型任务和混合型任务

任务的优先级:中高低

任务的执行时间:长,中和短

任务的依赖性:是否依赖其他系统资源,如数据库连接。

常用阻塞队列:

 

 

 

关闭线程池:

shutdown和shutdownNow

工作原理:遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程

区别:shutdownNow首先将线程池的状态设置为STOP,然后尝试停止所有正在执行任务的线程,并返回执行任务的列表。

   shutdown:只是将线程池的状态设置为SHUTDOWN状态,然后中断没有正在执行任务的线程。

 

posted @ 2019-07-28 19:56  落叶随风起  阅读(213)  评论(0编辑  收藏  举报