深入浅出多线程(6)分析并行包线程池的设计与实现
2008-11-10 14:58
666 查看
在上篇中介绍了线程池的设计需求以及使用,在这里我们分析Concurrent包中线程池的实现类ThreadPoolExecutor的设计,是不是感
觉没意义,人家都实现了还分析啥?当然是提高我们自身的设计能力了。对于设计能力的提高,我认为一方面我们要在具体实践中,能够学习前人
总结的设计思想(比如设计模式之类的),根据具体上下文,能够融会贯通的使用他们。另一方面分析优秀的框架设计与实现也是很好的方式,当然JDK设计是最好的学习资料。闲话多了,切入主题,设计要点:
纵观在JDK1.5以前我们自己实现的线程池,还是Concurrent提供的线程池,在线程池中首先我们要两个容器维护 线程池中的线程 与 提交给线程池中的Task。
线程池与Task如何关联,什么样的Task才可以提交的该线程池中执行呢。所以我们要定义一个接口,分离线程池与具体
Task的耦合关系,ThreadPoolExecutor可以接受实现Runnable接口或者Callable接口(其实最后也是组装为Runnable接口)的具体Task。
线程池中的线程从Task队列中去Task执行。
以上就是线程池设计的要点。
在ThreadPoolExecutor中,有一个内部类Worker,实现了Runnable,也就是线程池中的线程,不言而喻,它的Run方法就是从Task队列
取Task,调用Task的run方法(Task 是实现了Runnable接口的),执行Task,依次类推,直到没有队列里面Task。看下图
了解了线程的创建以及执行Task的流程,下面让我们在看看ThreadPoolExecutor是如何触发创建线程池线程的呢? 何时启动线程池里的
线程执行Task呢?再这之前,我们先说明一下,在ThreadPoolExecutor中引入了两个描述线程池中线程数量的属性,corePoolSize和 maximumPoolSize
corePoolSize 初始化时线程池中线程的数量。
maximumPoolSize 线程池中的程的最大数量,当Task无法插入Task队列,线程池线程数量又达到maximumPoolSize时,启用Reject策略,
Reject过多的Task。
下图说明了当我们创建一个线程池,并提交Task时,ThreadPoolExecutor首先判断是否达到corePoolSize,没有就在创建一个线程,提高吞吐量。如果超过那么直接将该Task插入Task队列。
如果插入失败,说明Task队列已满,那么尝试是否达到maximumPoolSize,如果没有,那么创建而外的线程处理改
Task,减低Task失败率。
如果已经达到了maximumPoolSize,对不起,只能Reject了。
这其实是线程池设计处理Task的策略。大家可以细细体会,这个策略的优势。
到现在其实已经基本说明了ThreadPoolExecutor的设计了,其实设计思想是不是跟以前我们自个设计线程池都一样?只是在具体实现上更加完善,更加完美!
对了大家如果感兴趣可以看看ThreadPoolExecutor如何优雅的Shutdown,这些设计实现细节,都可以在我们的实践中应用。
觉没意义,人家都实现了还分析啥?当然是提高我们自身的设计能力了。对于设计能力的提高,我认为一方面我们要在具体实践中,能够学习前人
总结的设计思想(比如设计模式之类的),根据具体上下文,能够融会贯通的使用他们。另一方面分析优秀的框架设计与实现也是很好的方式,当然JDK设计是最好的学习资料。闲话多了,切入主题,设计要点:
纵观在JDK1.5以前我们自己实现的线程池,还是Concurrent提供的线程池,在线程池中首先我们要两个容器维护 线程池中的线程 与 提交给线程池中的Task。
线程池与Task如何关联,什么样的Task才可以提交的该线程池中执行呢。所以我们要定义一个接口,分离线程池与具体
Task的耦合关系,ThreadPoolExecutor可以接受实现Runnable接口或者Callable接口(其实最后也是组装为Runnable接口)的具体Task。
线程池中的线程从Task队列中去Task执行。
以上就是线程池设计的要点。
在ThreadPoolExecutor中,有一个内部类Worker,实现了Runnable,也就是线程池中的线程,不言而喻,它的Run方法就是从Task队列
取Task,调用Task的run方法(Task 是实现了Runnable接口的),执行Task,依次类推,直到没有队列里面Task。看下图
了解了线程的创建以及执行Task的流程,下面让我们在看看ThreadPoolExecutor是如何触发创建线程池线程的呢? 何时启动线程池里的
线程执行Task呢?再这之前,我们先说明一下,在ThreadPoolExecutor中引入了两个描述线程池中线程数量的属性,corePoolSize和 maximumPoolSize
corePoolSize 初始化时线程池中线程的数量。
maximumPoolSize 线程池中的程的最大数量,当Task无法插入Task队列,线程池线程数量又达到maximumPoolSize时,启用Reject策略,
Reject过多的Task。
下图说明了当我们创建一个线程池,并提交Task时,ThreadPoolExecutor首先判断是否达到corePoolSize,没有就在创建一个线程,提高吞吐量。如果超过那么直接将该Task插入Task队列。
如果插入失败,说明Task队列已满,那么尝试是否达到maximumPoolSize,如果没有,那么创建而外的线程处理改
Task,减低Task失败率。
如果已经达到了maximumPoolSize,对不起,只能Reject了。
这其实是线程池设计处理Task的策略。大家可以细细体会,这个策略的优势。
到现在其实已经基本说明了ThreadPoolExecutor的设计了,其实设计思想是不是跟以前我们自个设计线程池都一样?只是在具体实现上更加完善,更加完美!
对了大家如果感兴趣可以看看ThreadPoolExecutor如何优雅的Shutdown,这些设计实现细节,都可以在我们的实践中应用。
相关文章推荐
- 深入浅出多线程(6)分析并行包线程池的设计与实现
- 深入浅出多线程(6)分析并行包线程池的设计与实现[转载]
- 深入浅出多线程(5)以并行包线程池为例说说线程池的设计需求及使用[转载]
- 深入浅出多线程(5)以并行包线程池为例说说线程池的设计需求及使用
- Java 多线程:分析线程池的实现原理
- Tiger Concurrent Practice --日志分析并行分解设计与实现
- [并发并行]_[线程池]_[Programming With POSIX Threads的线程池实现分析1]
- Java 多线程:分析线程池的实现原理
- Tiger Concurrent Practice --日志分析并行分解设计与实现
- [并发并行]_[pthread]_[线程池的简单设计与实现]
- Linux多线程实践(9) --简单线程池的设计与实现
- 优雅设计封装基于Okhttp3的网络框架(三):多线程下载功能核心实现 及 线程池、队列机制、终止线程解析
- Tiger Concurrent Practice --日志分析并行分解设计与实现收藏
- [并发并行]_[pthread]_[线程池的简单设计与实现]
- android 多线程 - 并行包线程池为例说说线程池的设计需求及使用
- Tiger Concurrent Practice --日志分析并行分解设计与实现
- 多线程之:几种线程池的实现算法分析
- Tiger Concurrent Practice --日志分析并行分解设计与实现
- 基于ProActive的分布式并行Web Spider的设计与实现
- Unix主机安全漏洞分析及漏洞扫描器的设计与实现