22 Executor与线程池

线程是一个重量级的对象,应该避免频繁创建和销毁。原因:创建线程需要调用操作系统API,然后os为线程分配资源

线程池使用的生产者-消费者模式:线程池的使用者是生产者,线程池本身就是消费者,工作队列就是那么拥塞队列。线程池会根据初始化的大小申请这些数量的线程,此时线程里并没有任务,同时线程池有一个工作队列,在初始化阶段也可被初始化。execute()方法提交一个工作方法,也就是给线程池里的线程提交一个干活的模板,这些线程都根据这个模板分别处理工作队列中的任务。当然,处理的过程中可能会有其他新的任务进来,放入到工作队列中等待。


使用 Java 中的线程池

Java 提供的线程池相关的工具类中,最核心的是 ThreadPoolExecutor

ThreadPoolExecutor初始化参数

把线程池类比为一个项目组,而线程就是项目组的成员。
corePoolSize:表示线程池保有的最小线程数。有些项目很闲,但是也不能把人都撤了,至少要留 corePoolSize 个人坚守阵地。

maximumPoolSize:表示线程池创建的最大线程数。当项目很忙时,就需要加人,但是也不能无限制地加,最多就加到 maximumPoolSize 个人。当项目闲下来时,就要撤人了,最多能撤到 corePoolSize 个人。

keepAliveTime & unit:上面提到项目根据忙闲来增减人员,那在编程世界里,如何定义忙和闲呢?很简单,一个线程如果在一段时间内,都没有执行任务,说明很闲,keepAliveTime 和 unit 就是用来定义这个“一段时间”的参数。也就是说,如果一个线程空闲了keepAliveTime & unit这么久,而且线程池的线程数大于 corePoolSize ,那么这个空闲的线程就要被回收了。

workQueue:工作队列,和上面示例代码的工作队列同义。

threadFactory:通过这个参数你可以自定义如何创建线程,例如你可以给线程指定一个有意义的名字。

handler:通过这个参数你可以自定义任务的拒绝策略。如果线程池中所有的线程都在忙碌,并且工作队列也满了(前提是工作队列是有界队列),那么此时提交任务,线程池就会拒绝接收。至于拒绝的策略,你可以通过 handler 这个参数来指定。

        1 .CallerRunsPolicy:提交任务的线程自己去执行该任务。  

        2. AbortPolicy:默认的拒绝策略,会 throws RejectedExecutionException。

        3.DiscardPolicy:直接丢弃任务,没有任何异常抛出。

        4.DiscardOldestPolicy:丢弃最老的任务,其实就是把最早进入工作队列的任务丢弃,然后把新任务加入到工作队列。

Executors静态工厂类提供了快速创建线程池的方法

1. ExecutorServiceexecutorService = Executors.newSingleThreadExecutor();  创建一个单线程化的Executor

2.ExecutorServiceexecutorService = Executors.newCachedThreadPool();  创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果没有可用的线程,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。

3.ExecutorServiceexecutorService = Executors.newFixedThreadPool(大小); 创建固定数目线程的线程池

4.ExecutorServiceexecutorService = Executors.newScheduledThreadPool(大小);  创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

Executors提供的许多方法使用的无界的工作队列,高负载情况下可能会OOM,不安全,不建议使用。强烈建议使用有界队列

https://blog.csdn.net/weixin_40304387/article/details/80508236   这篇文章很不错,对了解Executor框架有帮助。

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