8应用线程池
有些类型的任务需要明确指定一个执行策略,如依赖性任务、采用线程限制的任务,对响应时间敏感的任务、使用ThreadLocal的任务。(只有当线程本地thread_local()值的生命周期被限制在当前任务种时,在池的某线程中使用ThreadLocal才有意义;在线程池中,不应该使用ThreadLocal传递任务间的数值)
当任务都是同类的、独立时,线程池才有最佳的工作表现。
8.1线程饥饿死锁
在线程池中,如果一个任务依赖于其他任务的执行,就可能产生死锁。如:对于一个单线程化的Executor,一个任务将另一个任务提交到相同的Executor中,并等待提交的任务的结果,总会引起死锁。
第二个任务滞留在工作队列中,直到第一个任务完成;但第一个任务不会完成,因为它在等待第二个任务的完成。——这就是线程饥饿死锁。
因此,无论何时,提交一个非独立的Executor任务时,要明确出现线程饥饿死锁的可能性,且在代码或者配置文件以及其他可以配置Executor的地方,任何有关池的大小和配置约束都要写入文档。
8.1.2耗时操作
耗时任务会造成线程地堵塞,还会拖长服务时间。解决之道:限定任务的等待资源的时间。
大部分平台类库中的阻塞方法,同时提供了限时、非限时的2个版本,如Thread.join/BlockingQueue.put/CountDownLatch.await/Selector.select
8.2定制线程池大小
池的长度应该由某种配置机制来提供,不要硬编码,当然无须特别准确,只要以防过大或过小。
8.3配置ThreadPoolExcutor
核心池大小(Core Pool SIze)、最大池大小(max Pool Size)、存活时间(Keep Live Time)共同管理线程的创建与销毁。
核心池大小(Core Pool SIze)是目标的大小,线程池的实现试图维护池的大小:即没有任务执行,池的大小也等于核心池的大小;且直到工作队列充满时,池都不会创建更多的线程;
最大池大小(max Pool Size)是可同时活动的线程数的上限。如果一个线程已经闲置的时间超过了存活时间(Keep Live Time),会成为被回收的候选者,如果当前池的大小超过了核心池的大小,线程池会终止它。
Public ThreadPoolExecutor(int CorePoolSize,int maxPoolSize,long keepLiveTime,TimeUnit unit,……)
通过调节核心池的大小与存活时间,可以促进线程池归还空闲线程占有的资源。
newFixedThreadPool:工厂为请求的池设定了核心池的大小,最大池的大小,永不会超时;
newCachedThreadPool:工厂将最大池大小设置为Integer.MAX_VALUE,核心池大小为0,超时1分钟
8.3.2管理队列任务
ThreadPoolExecutor允许提供了一个BlockingQueue来持有等待执行的任务,任务排队有3种基本方法:无限队列,有限队列,同步移交。
newFixedThreadPool和newSingleThreadExecutor默认使用的是一个无限的LinkedBlockingQueue,如果所有的工作者线程都处于忙碌状态,任务将会在队列中等候;如果任务持续的快速到达,超过了它们被处理的速度,队列也会无限的增加。
稳妥的资源管理策略是使用有线的队列(如ArrayBlockingQueue、有限的LinkedBlockingQueue、PriorityBlockingQueue)
有界队列有助于避免资源耗尽的情况发生,但队列满时,要有相应的“饱和策略”处理。
newCachedThreadPool工厂提供了比定长的线程池更好的队列等候性能,它是Executor的一个很好的默认选择。
8.3.3饱和策略
当一个有线队列充满时,饱和策略开始生效。
ThreadPoolExecutor的饱和策略可以通过调用setRejectedExectionHandler来修改(如果任务提交到一个已经关闭的Executor时,也会用到饱和策略)
JDK提供了几种不同的RejectedExectionHandler实现,每一个实现不同的饱和策略:AbortPolicy、CallerRunsPolicy、DiscardPolicy、DiscardOldestPolicy.
默认的中止(abort)策略引起Executor抛出异常;调用者捕获异常,编写满足自己需求的处理代码;
当最新提交的任务不能进入队列等候执行时,“遗弃(Discard)”策略会放弃这个任务;
“遗弃最旧的(Discard——oldest)”策略选择丢弃的任务,是本应接下来执行的任务,该策略还会尝试重新提交新任务。(如果工作队列是优先级队列,那么遗弃最旧的策略选择丢弃的是刚好优先级最大的元素,所以混合使用遗弃最旧的饱和策略与优先级不可行)
“调用者运行(Call_runs)”策略的实现形式,既不会丢弃哪个任务,也不会抛出异常。它会把一些任务推回到调用者那里,以此缓解新任务流。它不会在线程池中执行最新的任务,但会在一个调用了executor的线程中执行。
8.3.4线程工厂
线程池创建线程,要通过一个线程工厂实现。默认的线程工厂创建了一个新的、非后台的线程。
ThreadFactory只有唯一的方法: .newThread()。它会在线程池需要创建一个新线程时调用。
8.4拓展ThreadPoolExecutor
它提供了几个“钩子”让子类去覆盖——beforeExecute、afterExecute、terminate——用于拓展ThreadPoolExecutor的行为。
(可以用于添加日志、时序、监视器、统计信息)
无论是正常从run返回,还是抛出异常,afterExecute会调用。
Terminate线程池关闭时调用。
Terminate可以用于释放Executor在生命周期中分配到的资源,还可以发出通知、记录日志、完成统计信息。
8.5并行递归算法
当每一个迭代彼此独立,且完成循环时,每个迭代的工作意义都足够大,足以弥补管理一个新任务的开销时,这个顺序循环是适合并行的。
9 GUI应用程序
几乎所有的GUI工具集都实现为“单线程化子系统”,意味着所有GUI的活动都被限制在一个单独的线程中,如Swing、SWT。
早期GUI:GUI事件在“主事件循环”进行处理;
现代GUI:创建一个专门的线程,事件派发线程EDI来处理GUI事件
(多线程GUI易受死锁影响)
单线程化的GUI框架通过线程限制来达到线程安全性,所有GUI中的对象,包括可视化组件和数据模型,都只能被事件线程访问。
Swing的线程限制
Swing的单线程规划:Swing的组件和模型只能在事件分派线程中被创建、修改和请求。
相关推荐
这本"Java并发编程学习笔记"可能是作者在深入研究Java并发特性、工具和最佳实践过程中积累的心得体会。下面,我们将根据这个主题,探讨一些关键的Java并发编程知识点。 1. **线程与进程**:在多任务环境中,线程是...
Java并发编程是Java开发中必不可少的一部分,涉及到多线程、同步机制、线程池以及并发工具类等多个核心知识点。以下是对这些主题的详细说明: 1. **线程安全与锁 Synchronized 底层实现原理**: 线程安全是指在多...
Java并发编程学习笔记,研究JAVA并发多线程编程的一本教程,使用并发技术可以开发出并行算法,充分利用多处理器的计算能力,避免硬件资源浪费。目前,在JAVA并发编程方面的论述系统且内容详实的技术资料不太多,Java...
### Java并发编程实践笔记知识点详解 #### 一、保证线程安全的方法 1. **不要跨线程访问共享变量:** 当多个线程共享某个变量时,若其中一个线程修改了该变量,其他线程若没有正确同步,则可能读取到错误的数据。...
### Java并发编程学习笔记知识点详解 #### 一、Java并发编程概述 Java并发编程是指在Java应用程序中同时执行多个操作的技术。它通过多线程、线程池等机制实现资源的有效利用,提高程序运行效率。Java并发编程的...
Java并发编程是Java开发中的重要领域,它涉及到多线程、同步、锁机制、线程池等关键概念,是提高程序性能和效率的关键技术。在Java中,并发编程的运用可以充分利用多核处理器的能力,实现高效的多任务处理。以下是对...
Java并发编程系列心得笔记,可以参考,欢迎共同交流学习
本文将基于文档《Java并发编程与高并发解决方案-学习笔记***.pdf》中提供的内容,来详细阐述并发编程和高并发的基本概念、CPU多级缓存与缓存一致性、以及Java内存模型。 ### 并发与高并发概念 在现代多线程编程中...
Java并发编程 背景介绍 并发历史 必要性 进程 资源分配的最小单位 线程 CPU调度的最小单位 线程的优势 (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 ...
Java并发编程与高并发解决方案是开发高性能应用的关键技术。在基础篇中,主要涉及以下几个重要知识点: 1. **并发编程基础** - **并发**:并发是指在一个时间段内,多个线程交替执行,使得系统看起来像是同时处理...
Java并发编程 学习资料
java并发编程与并发解决方案是自己多年开发和学习的笔记,有助于(ˇˍˇ) 想~进一步提高的java开发工程师或架构师深入的学习java架构并发处理。同时,它也是 在实际工作中多年高并发解决方案和经验的总结
自己总结的java并发编程的笔记,绘制了详细的思维导图,每个思维导图中均有详细的博文解释,方便大家学习和理解,免费分享给大家。
### Java并发编程与高并发解决方案知识点总结 #### 一、并发与高并发基本概念 ##### 1.1 并发 - **定义**: 指一个程序在同一时刻拥有两个或更多的线程,这些线程可以在单核或多核处理器上运行。 - **单核处理器上...
"JUC并发编程学习笔记(硅谷)"很可能包含了关于Java并发工具集(Java Util Concurrency, JUC)的深入理解和实战经验。JUC是Java标准库提供的一套强大的并发处理工具,它极大地简化了多线程编程,提高了程序的可读性...
《Java并发编程之美》学习笔记 《Java concurrency programming》learning note
学习Java并发编程时,锁的概念是无法回避的。锁是同步的一种机制,用来控制多个线程访问共享资源的顺序。在Java中,锁主要有两种类型:内置锁和显示锁。内置锁使用synchronized关键字实现,而显示锁则是通过java....
Java并发库是Java平台中的核心组件,它为多线程编程提供了丰富的工具和接口,使得开发者能够高效、安全地实现并发程序。在Java并发库中,ExecutorService接口和相关的线程池是其核心部分,它们提供了线程管理和任务...
这篇“Java线程编程学习笔记(二)”很可能是对Java并发编程深入探讨的一部分,特别是涉及多线程示例的实践应用。我们将从标题、描述以及标签来推测可能涵盖的知识点,并结合"Multi-Threads Demo"这一压缩包文件名来...