当前位置:首页 > 开发 > 编程语言 > Java > 正文

Java并发编程学习笔记(3)

发表于: 2015-01-24   作者:aoyouzi   来源:转载   浏览次数:
摘要: 8应用线程池 有些类型的任务需要明确指定一个执行策略,如依赖性任务、采用线程限制的任务,对响应时间敏感的任务、使用ThreadLocal的任务。(只有当线程本地thread_local()值的生命周期被限制在当前任务种时,在池的某线程中使用ThreadLocal才有意义;在线程池中,不应该使用ThreadLocal传递任务间的数值)   当任务都是同类的、独立时,线程池才有最佳的工

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种基本方法:无限队列,有限队列,同步移交。

 

newFixedThreadPoolnewSingleThreadExecutor默认使用的是一个无限的LinkedBlockingQueue,如果所有的工作者线程都处于忙碌状态,任务将会在队列中等候;如果任务持续的快速到达,超过了它们被处理的速度,队列也会无限的增加。

 

稳妥的资源管理策略是使用有线的队列(如ArrayBlockingQueue、有限的LinkedBlockingQueuePriorityBlockingQueue

有界队列有助于避免资源耗尽的情况发生,但队列满时,要有相应的“饱和策略”处理。

 

newCachedThreadPool工厂提供了比定长的线程池更好的队列等候性能,它是Executor的一个很好的默认选择。

 

8.3.3饱和策略

当一个有线队列充满时,饱和策略开始生效。

ThreadPoolExecutor的饱和策略可以通过调用setRejectedExectionHandler来修改(如果任务提交到一个已经关闭的Executor时,也会用到饱和策略)

 

JDK提供了几种不同的RejectedExectionHandler实现,每一个实现不同的饱和策略:AbortPolicyCallerRunsPolicyDiscardPolicyDiscardOldestPolicy.

 

默认的中止(abort)策略引起Executor抛出异常;调用者捕获异常,编写满足自己需求的处理代码;

当最新提交的任务不能进入队列等候执行时,“遗弃(Discard)”策略会放弃这个任务;

“遗弃最旧的(Discard——oldest)”策略选择丢弃的任务,是本应接下来执行的任务,该策略还会尝试重新提交新任务。(如果工作队列是优先级队列,那么遗弃最旧的策略选择丢弃的是刚好优先级最大的元素,所以混合使用遗弃最旧的饱和策略与优先级不可行)

 

“调用者运行(Call_runs)”策略的实现形式,既不会丢弃哪个任务,也不会抛出异常。它会把一些任务推回到调用者那里,以此缓解新任务流。它不会在线程池中执行最新的任务,但会在一个调用了executor的线程中执行。

 

8.3.4线程工厂

线程池创建线程,要通过一个线程工厂实现。默认的线程工厂创建了一个新的、非后台的线程。

ThreadFactory只有唯一的方法: .newThread()。它会在线程池需要创建一个新线程时调用。

 

8.4拓展ThreadPoolExecutor

它提供了几个“钩子”让子类去覆盖——beforeExecuteafterExecuteterminate——用于拓展ThreadPoolExecutor的行为。

(可以用于添加日志、时序、监视器、统计信息)

 

无论是正常从run返回,还是抛出异常,afterExecute会调用。

Terminate线程池关闭时调用。

 

Terminate可以用于释放Executor在生命周期中分配到的资源,还可以发出通知、记录日志、完成统计信息。

 

8.5并行递归算法

当每一个迭代彼此独立,且完成循环时,每个迭代的工作意义都足够大,足以弥补管理一个新任务的开销时,这个顺序循环是适合并行的。

 

9 GUI应用程序

几乎所有的GUI工具集都实现为“单线程化子系统”,意味着所有GUI的活动都被限制在一个单独的线程中,如SwingSWT

 

早期GUIGUI事件在“主事件循环”进行处理;

现代GUI:创建一个专门的线程,事件派发线程EDI来处理GUI事件

(多线程GUI易受死锁影响)

 

单线程化的GUI框架通过线程限制来达到线程安全性,所有GUI中的对象,包括可视化组件和数据模型,都只能被事件线程访问。

 

Swing的线程限制

Swing的单线程规划:Swing的组件和模型只能在事件分派线程中被创建、修改和请求。

 

 

Java并发编程学习笔记(3)

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
关键字: 原子操作:原子为不可再分操作。 Violation :可见关键字。 Synchronized:内部隐示锁 Ree
为啥需要并发: 个人英雄主义,单人独写xx软件的传奇,回味孤独英雄的寂寞。 系统运行也不是单个计
关键字: 原子操作:原子为不可再分操作。 Violation :可见关键字。 Synchronized:内部隐示锁 Ree
CLH算法实现 CLH队列中的结点QNode中含有一个locked字段,该字段若为true表示该线程需要获取锁,且
NUMA与SMP SMP(Symmetric Multi-Processor),即对称多处理器结构,指服务器中多个CPU对称工作,每个
【转】http://blog.csdn.net/aesop_wubo/article/details/7533186 NUMA与SMP SMP(Symmetric Multi-P
(非原创) NUMA与SMP SMP(Symmetric Multi-Processor),即对称多处理器结构,指服务器中多个CPU对
1、引言 JAVA内置的锁(使用同步方法和同步块)一直以来备受关注,其优势是可以花最小的空间开销创
一. 对象块 代码如下: 1 public class TestObject { 2 int i; 3 int j; 4 { 5 System.out.println("
第三章主要讲的共享对象,这章有些内容比较抽象,我理解其中的一些东西费了一些周折。所以把这些理
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号