并发编程-线程池
文章目录线程池线程池原理线程池分类线程池为什么需要使用线程池?线程的创建和销毁都需要消耗系统资源,线程池可以复用已有的线程线程也是对象,线程池可以复用线程对象,减低内存消耗可以控制并发数量,并发数量过多,可能会导致资源消耗过多可以对线程进行统一管理线程池原理[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SmBclC3n-1595301423983)(https://
·
线程池
为什么需要使用线程池?
- 线程的创建和销毁都需要消耗系统资源,线程池可以复用已有的线程
- 线程也是对象,线程池可以复用线程对象,减低内存消耗
- 可以控制并发数量,并发数量过多,可能会导致资源消耗过多
- 可以对线程进行统一管理
线程池原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SmBclC3n-1595301423983)(https://raw.githubusercontent.com/chenxiao19920206/RedSpiderArticlePhotos/master/java-base/multi-thread/%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B8%BB%E8%A6%81%E7%9A%84%E5%A4%84%E7%90%86%E6%B5%81%E7%A8%8B.png)]
- 线程池线程数量 < 核心线程数,每次都会创建新的线程去处理任务
- 线程数量 == 核心线程数,则每次新加的任务都会添加到任务队列,线程会去任务队列取任务执行(体现线程复用)
- 当任务队列满了 && 线程数 < 最大线程数,则会创建救急线程去执行,执行完会被销毁
- 如果任务队列满了 && 线程数 = 最大线程数,则会执行拒绝策略
拒绝策略:
- 默认是抛出异常,ThreadPoolExecutor.AbortPolicy:默认拒绝处理策略,丢弃任务并抛出RejectedExecutionException异常。
- ThreadPoolExecutor.DiscardPolicy:丢弃新来的任务,但是不抛出异常。
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列头部(最旧的)的任务,然后重新尝试执行程序(如果再次失败,重复此过程)。
- ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务。
shutdown和shutdownNow
- shutdown方法后处于SHUTDOWN,线程池不接受新的任务,等待任务队列中的任务执行完成
- shutdownNow方法后处于STOP,线程池不接受新任务,并且在执行中的任务也不执行完强制退出
线程池分类
newCachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
- 每个线程都是救急线程,使用完会60s空闲后会被回收掉,采用synchronousQueue,每进来一个任务就会有一个线程去取,任务队列不保存任务
- 当需要执行很多短时间的任务时,CacheThreadPool的线程复用率比较高, 会显著的提高性能。而且线程60s后会回收,意味着即使没有任务进来,CacheThreadPool并不会占用很多资源。
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
- 核心线程数 = 最大线程数,只能创建核心线程,不能创建非核心线程。因为LinkedBlockingQueue的默认大小是Integer.MAX_VALUE,故如果核心线程空闲,则交给核心线程处理;如果核心线程不空闲,则入列等待,直到核心线程空闲
- 由于线程不会被回收,会一直卡在阻塞,所以没有任务的情况下, FixedThreadPool占用资源更多。
都几乎不会触发拒绝策略,但是原理不同。FixedThreadPool是因为阻塞队列可以很大(最大为Integer最大值),故几乎不会触发拒绝策略;CachedThreadPool是因为线程池很大(最大为Integer最大值),几乎不会导致线程数量大于最大线程数,故几乎不会触发拒绝策略。
newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
- 单线程线程池,如果这个唯一的线程不空闲,那么新来的任务会存储在任务队列里等待执行。
newScheduledThreadPool
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
- 定时任务线程池
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)