线程池
线程池:是一种利用池化技术思想来实现的线程管理技术,主要是为了复用线程、便利地管理线程和任务、并将线程的创建和任务的执行解耦开来。
线程池哪有写优点呢?
- 降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
- 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
- 提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
- 提供更多更强大的功能:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如可以允许任务延期执行或定期执行。
Executors线程池工具类创建线程池底层也是通过ThreadPoolExecutor创建线程池。所以ThreadPoolExecutor时非常核心的一个线程池类
任务进入优先级:先用核心线程完成任务,再进阻塞队列;阻塞队列满了,但是线程池的线程数量小于maxPoolExecutor,此时增加新的任务,会立即执行新的任务,而不会从队列中取任务。
一、ThreadPoolExecutor
线程池类图关系:
Executor 为函数式接口,线程池最顶级的接口。
1 public interface Executor { 2 void execute(Runnable command); 3 }
execute和submit方法不同?submit底层调用了execute,差别在RunnableFuture<T> ftask= new FautureTask(callable)这行代码。
1 execute只能提交Runnable类型的任务,submit既能提交Runnable又能提交Callable类型的任务
2 异常的捕捉:execute会直接抛出异常,submit会吃掉异常,通过Future的get方法将异常抛出
3 返回值:execute没有返回值,submit有返回值

ExecutorService接口:
public interface ExecutorService extends Executor { void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException; <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException; <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException; <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
FutureTask
FutureTask实现了RunnableFuture接口,RunnableFuture实现了Runnable和Future接口。
线程池使用时,callable当作参数传入submit方法中,方法体中callable传入FutureTask构造器中,再调用execute方法,参数为FutureTask。
非线程池使用时,FutureTask当作参数传入Thread线程构造器中。
中。FutureTask.get方法获得返回值。
ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize, //核心线程数 int maximumPoolSize, //最大线程数 long keepAliveTime, //空闲时存活时间 TimeUnit unit, //空闲时存活时间单位 BlockingQueue<Runnable> workQueue //阻塞队列
ThreadFactory threadFactory, //线程工厂,定义如何新建线程
RejectedExecutionHandler handler //拒绝策略
)
AbstractExecutorService
实现了ExecutorService接口,只有实现了submit、invokeAny、invokeAll方法。
二、Executors
线程池的使用
线程池的创建方法有7钟,但是可以分为两大类
一类是通过Executors实现
一类是通过ThreadPoolExecutors实现
Executors底层也是通过new ThreadPoolExecutors()创建线程池,所以线程池底层为ThreadPoolExecutors。
①单线程线程池:Single Thread Executor : 只有一个线程的线程池,因此所有提交的任务是顺序执行,
代码:Executors.newSingleThreadExecutor()
说明:创建大小为1的固定线程池,同时执行任务(task)的只有一个,其它的(任务)task都放在LinkedBlockingQueue中排队等待执行。
②缓存线程池(变长):Cached Thread Pool :短时间内处理大量工作的线程池,会根据任务数量产生对应的线程,并试图缓存线程以便重复使用,如果线程超过60秒内没执行,那么将被终止并从池中删除,
代码:Executors.newCachedThreadPool()
说明:使用时,放入线程池的task任务会复用线程或启动新线程来执行,注意事项:启动的线程数如果超过整型最大值后会抛出RejectedExecutionException异常,启动后的线程存活时间为一分钟。
③固定线程数线程池:Fixed Thread Pool : 拥有固定线程数的线程池,如果没有任务执行,那么线程会一直等待,
代码:Executors.newFixedThreadPool()
说明:创建固定大小(nThreads,大小不能超过int的最大值)的线程池,缓冲任务的队列为LinkedBlockingQueue,大小为整型的最大数,当使用此线程池时,在同执行的任务数量超过传入的线程池大小值后,将会放入LinkedBlockingQueue,在LinkedBlockingQueue中的任务需要等待线程空闲后再执行,如果放入LinkedBlockingQueue中的任务超过整型的最大数时,抛出RejectedExecutionException。(newFixedThreadPool的参数指定了可以运行的线程的最大数目,超过这个数目的线程加进去以后,不会运行。其次,加入线程池的线程属于托管状态,线程的运行不受加入顺序的影响。)
④周期性线程的线程池 : Scheduled Thread Pool : 用来调度即将执行的任务的线程池,
代码:Executors.newScheduledThreadPool()
⑤单线程周期性线程池:Single Thread Scheduled Pool : 只有一个线程,用来调度执行将来的任务,代码:
Executors.newSingleThreadScheduledExecutor()
说明:线程keepAliveTime为0,缓存任务的队列为DelayedWorkQueue,注意不要超过整型的最大值。
⑥WorkStealingPool(n):Java 8 新增创建线程池的方法,创建时如果不设置任何参数,则以当前机器处理器个数作为线程个数,此线程池会并行处理任务,不能保证执行顺序。
一旦你创建了一个线程池,你就可以往池中通过不同的方法提交执行任务
submit方法该可提交 Runnable 或者 Callable 到线程池中,返回一个 Future 实例表示任务的状态,如果你提交一个 Runnable 但参数没有T result,那么如果任务完成后 Future 对象返回 null。
execute方法传递Runnable到线程池中,没有返回值。
shutdown方法,等待线程都执行完毕后终止线程池,shutdownNow() 的方法来强制关闭线程池,执行中的线程也会被中断,所有尚未被执行的任务也将不会再执行。
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术