它是一个ExecutorService,使用线程池中的线程执行提交的任务。通常我们使用Executors框架,定义使用。
线程池主要用来解决两类问题:通过缓存一定数量的可用线程,避免频繁的线程创建,销毁,来提升执行大量异步任务的性能;资源管理,包括线程及任务。同时也维护一些诸如完成任务数等统计数据。
为了能够获得更广泛的适用性,此类提供了多个可调整的参数及扩展性钩子,但是,开发者通常更倾向于使用更为便捷的Executors框架,通过它预定义了各种类型线程池,如newCachedThreadPool(缓存类型的无界线程池),newFixedThreadPool(固定数量的线程池),newSingleThreadExecutor(单个线程的线程池)。
当然我们也可以通过此类自定义相应特性的线程池。
核心及最大线程池数量
ThreadPoolExecutor 会根据核心及最大线程数设定自动的调整线程池内线程的数量。
线程池何时创建新的线程:
当一个任务提交后,如果当前线程池内的可运行的线程(无论是否处于闲置状态)数量小于核心数量,那么就会创建新的线程;如果当前线程池内的线程数量处于核心数和最大数之间,则,只有在队列(排队等待处理的任务队列)满的时候会创建新的线程。
固定容量及无界线程池:
如果把核心数和最大数设置为相同的值,那么线程池就会变为固定容量的线程池;可以通过把最大数设置为一个极大的值,如Integer.MAX_VALUE,来创建一个可以自适应高并发任务的场景的线程池。核心数和最大值通常在线程池初始定义的时候通过构造参数传入,也可以通过相应的方法动态的进行变更配置。
自定义构造
默认情况下,线程池中的线程会在初始化时进行创建,然后在任务到达时运行。我们也可以通过方法prestartCoreThread或者prestartAllCoreThreads来预先运行线程。
新线程创建:
线程是通过ThreadFactory来创建的,如果没有明确定义,则会使用Executors默认的defaultThreadFactory来创建,先创建的线程会归在同一个分组,并且拥有相同的NORM_PRIORITY优先级别及非守护特性。我们可以通过定义相应的ThreadFactory来,自定义线程的名称,群组,优先级及守护特性。如果ThreadFactory的方法newThread()创建线程失败,返回null,那么Executor会继续运行,但是无法在处理新添加的任务。
生存时间:
如果线程池当前拥有的线程数量多于核心数,那么多于的线程会在空闲生存时间后被终止销毁。减少非活跃线程池的资源耗费,当需求增多时,再重新创建需要的线程放入线程池以供使用。生存时间可以通过getKeepAliveTime() 方法进行动态设置,如果设置为LONG.MAX_VALUE,那么闲置线程将不会被回收。通常keep-alive只适用于超过核心数的线程,我们也可以通过设置allowCoreThreadTimeOut(boolean)来应用到所有的线程。keepAliveTime不为0时起作用。
队列:
可以使用任意形式的阻塞队列来存放提交到线程池的任务。队列和线程池大小相关。
如果线程数小于核心数,那么线程池会优先创建新的线程,而不进行任务入队。
如果等于或者超过核心数,那么线程池会优先将任务入队,而不创建新的线程。
如果等于或者超过核心数且任务队列已满,在不超过最大数情况下,会进行新线程的创建,超过最大线程数,则会执行相应的丢弃策略。
三种排队策略:
直接传递:通常使用SynchronousQueue队列,直接将任务转交给线程,而不进行任务的存储。如果没有线程接收任务,那么任务入队会失败,所以此种情况,会直接创建新的线程。这种策略,对于处理任务间有依赖关系的情况,避免了队列任务遍历。直接传递策略需要相应的无界线程池策略支持,以避免任务被丢弃,拒绝。者反过来也可能引发当处理速度小于任务到达速度时,线程池的无限增长。
无界队列:通常使用LinkedBlockingQueue,不预定义容量。因为队列无界,所以,核心线程都忙时,不会创建新的线程,可能导致任务的无限堆积,无界队列情况下,线程池最大值配置将不起作用。无界队列情况适用于任务间没有联系,各自肚独自运行的场景。例如,对于web系统,可以用来处理突发请求平滑处理。
有界队列:例如ArrayBlockingQueue,可以避免使用无界线程池时的的资源耗尽。但是,却不利于对请求处理的协调和控制。队列大小和线程池最大值参数之间会进行平衡处理。如:大容量队列和小容量线程池的使用可以最小化cpu使用,系统资源耗费及线程间上下文切换带来的负担。但是会造成吞吐量的降低,也无法充分使用系统的调度能力;相应的使用小队列则需要较大的线程池容量,可能造成cpu繁忙,进而造成系统无法调度现象,也会造成系统吞吐量的降低。
任务丢弃:
Executor关闭时,提交的任务会被丢弃;使用有界队列及有界线程池时,并且都已达到边界值时,提交的任务会被丢弃。任务丢弃会通过 RejectedExecutionHandler执行相应的丢弃策略。
默认AbortPolicy:抛出运行时异常
CallerRunsPolicy:使用提交任务的线程执行任务,这种策略提供了一种反馈机制,减缓了新任务的提交速度。
DiscardPolicy:直接丢弃任务。
DiscardOldestPolicy:丢弃任务队列头部的任务。
也可以自定义相应的丢弃策略,特别需要注意针对特定线程池容量及队列容量情况下的策略。
ThreadPoolExecutor提供了相应的beforeExecute及afterExecute方法用于在任务执行的前后执行相应的操作,如,调整任务执行的环境,重新初始化ThreadLocals,收集统计信息,添加日志等。另外,可以重写terminated方法,以在Executor完全关闭后做相应的处理。
如果钩子或者回调函数抛出异常,那么内部工作线程也会失败。
getQueue通常用于调试,其它情况不建议使用。
remove和purge可以用于大量任务取消情况下的任务队列处理。
当线程池不再被应用系统使用,并且,内部的也没有线程的时候,会被自动关闭。如果存在被闲置线程池重新声明的情况,那么需要确保对内部线程设置了合适的生存时间,及使用0核心数,设置线程可超时策略等。
相关推荐
* 降低了系统的开销:ThreadPoolExecutor 可以重复使用线程,避免了频繁创建和销毁线程的开销。 * 提高了系统的灵活性:ThreadPoolExecutor 可以根据不同的工作负载动态地调整线程池的大小。 ThreadPoolExecutor 的...
ThreadPoolExecutor使用和思考
根据提供的文件信息,我们可以深入探讨线程池`ThreadPoolExecutor`的工作原理及其实现细节,同时也会涉及并发编程中的一些关键概念和技术。 ### 线程池`ThreadPoolExecutor`概述 `ThreadPoolExecutor`是Java中非常...
- 线程池:ThreadPoolExecutor的使用和参数配置。 6. **服务(Service)**: - 后台服务的启动方式,生命周期及特点。 - IntentService:单线程执行任务的Service,自动管理生命周期。 7. **权限管理**: - 运行...
根据给定文件的信息,我们可以深入探讨Java中`ThreadPoolExecutor`线程池的底层实现原理,特别是其核心数据结构`ctl`以及线程池的各种状态转换。以下是对这些知识点的详细解释: ### 一、线程池`ThreadPoolExecutor...
- 了解线程池的概念,如ThreadPoolExecutor的使用和配置。 5. **内存模型与垃圾回收** - 理解Java内存模型(JMM),包括堆内存、栈内存和方法区。 - 掌握对象的生命周期,包括创建、使用、垃圾回收。 - 了解几...
- 调优工具:熟悉JVisualVM、JConsole等JVM监控工具的使用,以及常见的性能调优策略。 8. **设计模式** - 常见设计模式:了解单例、工厂、观察者、装饰器、适配器、代理等设计模式的实现和应用场景。 9. **...
- ThreadPoolExecutor:线程池的使用和优化。 4. **Android性能优化**: - 内存优化:避免内存泄漏,使用LeakCanary检测内存泄漏。 - 性能监控:使用Systrace、Traceview、HierarchyViewer等工具进行性能分析。 ...
ThreadPoolExecutor的使用和Android常见的4种线程池使用介绍
线程池原理-ThreadPoolExecutor源码解析 1.构造方法及参数 2.阻塞对列: BlockingQueue 3.线程工厂: DefaultThreadFactory 4.拒绝策略: RejectedExecutionHandler 5.执行线程 Executor
在Java面试中,面试官通常会关注候选人的技术深度、广度以及问题解决能力。这份“java面试必问面试宝典--千方百计”很可能是总结了众多面试者的经验,包含了Java核心技术、面试技巧以及应对策略。以下是一些可能涵盖...
- ExecutorService与ThreadPoolExecutor的使用。 3. **集合框架**: - List、Set、Queue接口及其常用实现类的特性。 - HashMap、HashSet、ArrayList、LinkedList的工作原理。 - ConcurrentHashMap线程安全的...
在Java高级面试中,面试官通常会关注应聘者对核心概念、高级特性和实际问题解决能力的掌握。针对“深圳-OPPO-Java高级”这个主题,我们可以预想面试会涵盖多个关键知识点,包括但不限于: 1. **Java基础**: - 类...
【Java核心知识面试】-Java面试精选72题.pdf 是一本专门为Java开发者准备的面试指南,涵盖了Java语言的各个方面,旨在帮助求职者强化基础,掌握关键技能,以便在面试中脱颖而出。以下是根据这本书的标题和描述所提炼...
在Java编程领域,多线程开发是不可或缺的一部分,特别是在面试环节,面试官常常会通过考察开发者对多线程的理解和实战经验来评估其技术水平。JavaConcurrent是Java平台提供的高级并发API,它使得多线程编程更加高效...
- 线程池的使用,如ExecutorService和ThreadPoolExecutor。 7. **内存模型与垃圾回收**: - Java内存区域划分,如堆、栈、方法区、本地方法栈。 - 垃圾回收机制,包括GC算法和内存调优。 8. **IO与NIO**: - ...
- 线程池的理解与使用,如ExecutorService和ThreadPoolExecutor。 7. **反射**: - 如何通过Class对象动态获取类的信息并创建对象。 - 使用反射调用私有方法和访问私有成员变量。 8. **设计模式**: - 常见...
根据提供的文件标题、描述、标签以及部分内容链接,我们可以推断出这份资料主要聚焦于Java开发者的中级面试准备。下面将围绕这一主题展开一系列重要的Java知识点,帮助求职者更好地准备面试。 ### Java基础知识 ##...
- 线程池:熟悉ExecutorService和ThreadPoolExecutor,以及线程池的配置和优化。 - 并发工具类:了解ConcurrentHashMap、CountDownLatch、CyclicBarrier、Semaphore等并发工具的用法。 4. **框架** - Spring框架...
- 线程池:使用ExecutorService和ThreadPoolExecutor进行线程管理。 5. **网络编程**: - Socket编程:理解TCP和UDP协议,如何使用Socket进行网络通信。 - HttpURLConnection和HttpClient:掌握HTTP请求的发送与...