共计 2067 个字符,预计需要花费 6 分钟才能阅读完成。
download:拉勾 - 算法突击特训营 3 期【百度云】
Java 线程池 Executor 详解
咱们最常使用的 Executors 实现创建线程池使用线程次要是用上述类图中提供的类。在上边的类图中,蕴含了一个 Executor 框架,它是一个根据一组执行策略的调用调度执行和管制异步工作的框架,目标是提供一种将工作提交与工作如何运行别来到的机制。它蕴含了三个 executor 接口:
Executor: 运行新工作的简略接口
ExecutorService:扩大了 Executor,增加了用来治理执行器生命周期和工作生命周期的方法
ScheduleExcutorService:扩大了 ExecutorService,反对 Future 和定期执行工作
线程池的好处
升高资源消耗 - 重用存在的线程,缩小对象创建、沦亡的开销,性能好
提高响应速度 - 可无效管制最大并发线程数,提高系统资源应用率,同时可能避免过多资源竞争,避免阻塞。当工作到达时,工作可不必等待线程创建就能立即执行
提高线程的可管理性 - 提供定时执行、定期执行、单线程、并发数管制等功能。
new Thread 的弊病
每次 new Thread 新建对象,性能差
线程不足对立治理,可能无限度的新建线程,相互竞争,可能占用过多的系统资源导致死机或者 OOM(out of memory 内存溢出),这种问题的原因不是因为单纯的 new 一个 Thread,而是可能因为程序的 bug 或者设计上的缺点导致不断 new Thread 造成的。
缺少更多功能,如更多执行、定期执行、线程中断。
线程池核心类 -ThreadPoolExecutor
参数说明:ThreadPoolExecutor 一共有七个参数,这七个参数配合起来,形成了线程池弱小的功能。
corePoolSize:核心线程数量
maximumPoolSize:线程最大线程数
workQueue:阻塞队列,存储等待执行的工作,很重要,会对线程池运行过程产生重大影响
当咱们提交一个新的工作到线程池,线程池会根据以后池中正在运行的线程数量来决定该工作的处理形式。处理形式有三种:
1、间接切换(SynchronusQueue)
2、无界队列(LinkedBlockingQueue)能够创建的最大线程数为 corePoolSize, 这时 maximumPoolSize 就不会起作用了。当线程池中所有的核心线程都是运行状态的时候,新的工作提交就会放入等待队列中。
3、有界队列(ArrayBlockingQueue)最大 maximumPoolSize,能够升高资源消耗,然而这种形式使得线程池对线程调度变的更艰巨。因为线程池与队列容量都是无限的。所以想让线程池的吞吐率和处理工作达到一个正当的范畴,又想使咱们的线程调度绝对简略,并且还尽可能升高资源的消耗,咱们就需要正当的限度这两个数量
调配技巧:[如果想升高资源的消耗包含升高 cpu 使用率、操作系统资源的消耗、上下文切换的开销等等,可能设置一个较大的队列容量和较小的线程池容量,这样会升高线程池的吞吐量。如果咱们提交的工作常常发生阻塞,咱们可能调整 maximumPoolSize。如果咱们的队列容量较小,咱们需要把线程池大小设置的大一些,这样 cpu 的使用率相对来说会高一些。然而如果线程池的容量设置的过大,提高工作的数量过多的时候,并发量会减少,那么线程之间的调度就是一个需要考虑的问题。这样反而可能会升高处理工作的吞吐量。]
keepAliveTime:线程没有工作执行时最多保持多久工夫终止(当线程中的线程数量大于 corePoolSize 的时候,如果这时没有新的工作提交核心线程外的线程不会立即销毁,而是等待,直到超过 keepAliveTime)
unit:keepAliveTime 的工夫单位
threadFactory:线程工厂,用来创建线程,有一个默认的工场来创建线程,这样新创建进去的线程有雷同的优先级,是非守护线程、设置好了名称)
rejectHandler:当拒绝处理工作时(阻塞队列满) 的策略(AbortPolicy 默认策略间接抛出异样、CallerRunsPolicy 用调用者所在的线程执行工作、DiscardOldestPolicy 抛弃队列中最靠前的工作并执行当前任务、DiscardPolicy 间接抛弃当前任务)
corePoolSize、maximumPoolSize、workQueue 三者关系:如果运行的线程数小于 corePoolSize 的时候,间接创建新线程来处理工作。即使线程池中的其余线程是空闲的。如果运行中的线程数大于 corePoolSize 且小于 maximumPoolSize 时,那么只有当 workQueue 满的时候才创建新的线程去处理工作。如果 corePoolSize 与 maximumPoolSize 是雷同的,那么创建的线程池大小是固定的。这时有新工作提交,当 workQueue 未满时,就把请求放入 workQueue 中。等待空线程从 workQueue 取出工作。如果 workQueue 此时也满了,那么就使用另外的拒绝策略参数去执行拒绝策略。