后端 | Java | 线程池|环球实时

哔哩哔哩   2023-06-17 22:54:16

笔记来源:Java入门基础视频教程,java零基础自学就选黑马程序员Java入门教程


(资料图片仅供参考)

一、线程池概述

概念:

线程池就是一个可以复用线程的技术。

不适用线程池的问题:

如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能。

工作原理:

线程池通过提供固定的核心线程(工作线程WorkThread)和任务队列(WorkQueue)来工作,当核心线程都在忙时,新来的任务进入任务队列,等待核心线程的处理。

二、线程池实现的API、参数说明

JDK5.0起提供了代表线程池的接口,ExecutorService。

ExcutorService常用方法:

void execute(Runnable command):执行任务/命令,没有返回值,一般用来执行Runnable任务。

Future<T> submit(Callable<T> task):执行任务,返回未来任务对象获取线程结果,一般拿来执行Callable任务。

void submit():等任务执行完毕后关闭线程池。

List<Runnable> shutdownNow():立刻关闭,停止正在执行的任务,并返回队列中未执行的任务。

如何得到一个线程池对象:

方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。

ThreadPoolExecutor构造器的参数说明:

指定线程池的线程数量(核心线程):corePoolSize,不能小于0。

指定线程池可支持的最大线程数:maximumPoolSize,最大数量>=核心线程数量。

指定临时线程的最大存活时间:keepAliveTime,不能小于0。

指定存活时间的单位(秒、分、时、天):unit,时间单位。

指定任务队列:workQueue,不能为null。

指定用哪个线程工厂创建线程:threadFactory,不能为null。

指定线程忙,任务满时,新任务来了怎么办:handler,不能为null。

方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。

Executors的底层也是基于线程池的实现类ThreadPoolExecutor创建线程池对象的。

Executors得到线程池对象的常用方法:

public static ExecutorService newCachedThreadPool():线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了一段时间则会被回收掉。

public static ExecutorService newFixedThreadPool(int nThreads):创建固定线程数量的线程池,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程替代它。

public static ExecutorService newStringThreadExecutor():创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新线程。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize):创建一个线程池,可以实现在给定的延迟后运行任务,或者定期执行任务。

Executors使用可能存在的陷阱:

大型并发系统环境中使用Executors如果不注意可能会出现系统风险。

可能会出现OOM错误(Java.lang.OutOfMemoryError)。

三、线程池处理Runnable任务

ThreadPoolExecutor创建线程池对象:

新任务拒绝策略:

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常,是默认的策略。

ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常,这是不推荐的做法。

ThreadPoolExecutor.DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中。

ThreadPoolExecutor.CallerRunsPolicy:由主线程负责调用任务的run()方法从而绕过线程池直接执行。

给一个任务给线程池处理:

四、线程池处理Callable任务

五、线程池常见面试题

临时线程什么时候创建?

新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。

什么时候会开始拒绝任务?

核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝。

精彩推送