线程池 今天药忘吃喽~ 2022-12-10 08:57 6阅读 0赞 ## 1 为什么要用线程池? ## 线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。 这里借用《Java并发编程的艺术》提到的来说一下使用线程池的好处: * 降低资源消耗。 通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 * 提高响应速度。 当任务到达时,任务可以不需要的等到线程创建就能立即执行。 * 提高线程的可管理性。 线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。 ## 2 实现Runnable接口和Callable接口的区别 ## 如果想让线程池执行任务的话需要实现的Runnable接口或Callable接口。 Runnable接口或Callable接口实现类都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor执行。两者的区别在于 Runnable 接口不会返回结果但是 Callable 接口可以返回结果。 备注: 工具类Executors可以实现Runnable对象和Callable对象之间的相互转换。(Executors.callable(Runnable task)或Executors.callable(Runnable task,Object resule))。 ## 3 执行execute()方法和submit()方法的区别是什么呢? ## 1. execute() 方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否; 2. submit() 方法用于提交需要返回值的任务。线程池会返回一个Future类型的对象,通过这个Future对象可以判断任务是否执行成功,并且可以通过future的get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用 get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。 ## 4 如何创建线程池 ## 《阿里巴巴Java开发手册》中强制线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险 Executors 返回线程池对象的弊端如下: **FixedThreadPool** 和 **SingleThreadExecutor** : **允许请求的队列长度为 Integer.MAX\_VALUE ,可能堆积大量的请求,从而导致OOM**。 **CachedThreadPool** 和 **ScheduledThreadPool** : **允许创建的线程数量为 Integer.MAX\_VALUE ,可能会创建大量线程,从而导致OOM**。 方式一:通过构造方法实现 方式二:通过Executor 框架的工具类Executors来实现 我们可以创建三种类型的ThreadPoolExecutor: **FixedThreadPool** : 该方法返回一个固定线程数量的线程池。该线程池中的线程数量始终不变。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。 **SingleThreadExecutor**: 方法返回一个只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务。 **CachedThreadPool**: 该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。 ## 推荐使用创建线程方法 ## public class ThreadPoolDemo { // 线程数 public static final int THREAD_POOL_SIZE = 16; public static void main(String[] args) throws InterruptedException { // 使用 ThreadFactoryBuilder 创建自定义线程名称的 ThreadFactory ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() .setNameFormat("demo-pool-%d").build(); // 创建线程池,其中任务队列需要结合实际情况设置合理的容量 ThreadPoolExecutor executor = new ThreadPoolExecutor(THREAD_POOL_SIZE, THREAD_POOL_SIZE, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); // 新建 1000 个任务,每个任务是打印当前线程名称 for (int i = 0; i < 1000; i++) { executor.execute(() -> System.out.println(Thread.currentThread().getName())); } // 优雅关闭线程池 executor.shutdown(); executor.awaitTermination(1000L, TimeUnit.SECONDS); // 任务执行完毕后打印"Done" System.out.println("Done"); } } ## 线程池执行任务逻辑和线程池参数的关系 ## ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM2NzI5MDIx_size_16_color_FFFFFF_t_70_pic_center] 执行逻辑说明: * 判断核心线程数是否已满,核心线程数大小和corePoolSize参数有关,未满则创建线程执行任务 * 若核心线程池已满,判断队列是否满,队列是否满和workQueue参数有关,若未满则加入队列中 * 若队列已满,判断线程池是否已满,线程池是否已满和maximumPoolSize参数有关,若未满创建线程执行任务 * 若线程池已满,则采用拒绝策略处理无法执执行的任务,拒绝策略和handler参数有关 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM2NzI5MDIx_size_16_color_FFFFFF_t_70_pic_center]: /images/20221123/b46c124a3d35412581faa655b6014e7f.png
相关 Java 线程池、Runnable线程池、Callable线程池 线程池: 其实就是一个容纳多个线程的容器,其中的线程可以反复的使用,省去了频繁创建和销毁过程对象的操作,无需反复创建线程面消耗过多资源。 为什么要用线程池: 合理 青旅半醒/ 2023年02月26日 12:30/ 0 赞/ 58 阅读
相关 线程、线程池 创建线程的3种方法: package com.frank.threadPool.createThread; / @author 小石潭记 布满荆棘的人生/ 2022年10月22日 04:27/ 0 赞/ 388 阅读
相关 线程池 1.所谓线程池,就是程序的初始化阶段,就预先创建一批线程,每个线程都做好准备干活; 2.然后有一个任务列表,一开始为空,当有任务来了,就往任务列表里面添加;这个任务列表 痛定思痛。/ 2022年06月13日 13:22/ 0 赞/ 331 阅读
相关 线程池 西施越溪女,明艳光云海 最近用线程池和不用线程池做了个速度的测试,在这里备注下: 结果是速度不相上下; public static void main(Str 妖狐艹你老母/ 2022年05月20日 02:35/ 0 赞/ 285 阅读
相关 线程池 线程池 Java里面线程池的顶级接口是 java.util.concurrent.Executor , 但是严格意义上讲 Executor并不是一个线程池,而只是一个 迈不过友情╰/ 2022年03月06日 14:34/ 0 赞/ 403 阅读
相关 线程池 线程池 > 从字面义上来讲,是指管理一组同构工作线程的资源池。线程池是与工作队列密切相关的,其中在工作队列中(Worker Queue)保存了所有等待执行的任务。工作者( 清疚/ 2021年12月11日 03:35/ 0 赞/ 389 阅读
相关 线程池 可preStart一个或全部core thread 0,小于core则来一个任务建一个线程(firstTask),队列,额外线程,拒绝 一个AtomicInteger的 今天药忘吃喽~/ 2021年11月23日 03:40/ 0 赞/ 415 阅读
相关 线程池 1、先创建线程池 import java.util.concurrent.ArrayBlockingQueue; import java.util.concu 拼搏现实的明天。/ 2021年11月09日 14:28/ 0 赞/ 425 阅读
还没有评论,来说两句吧...