26、Java并发性和多线程-线程池
以下内容转自http://ifeve.com/thread-pools/:
线程池(Thread Pool)对于限制应用程序中同一时刻运行的线程数很有用。因为每启动一个新线程都会有相应的性能开销,每个线程都需要给栈分配一些内存等等。
我们可以把并发执行的任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程。只要池里有空闲的线程,任务就会分配给一个线程执行。在线程池的内部,任务被插入一个阻塞队列(Blocking Queue ),线程池里的线程会去取这个队列里的任务。当一个新任务插入队列时,一个空闲线程就会成功的从队列中取出任务并且执行它。
线程池经常应用在多线程服务器上。每个通过网络到达服务器的连接都被包装成一个任务并且传递给线程池。线程池的线程会并发的处理连接上的请求。以后会再深入有关Java实现多线程服务器的细节。
Java 5在java.util.concurrent包中自带了内置的线程池,所以你不用非得实现自己的线程池。你可以阅读我写的java.util.concurrent.ExecutorService的文章以了解更多有关内置线程池的知识。不过无论如何,知道一点关于线程池实现的知识总是有用的。
这里有一个简单的线程池实现:
public class ThreadPool {
private BlockingQueue taskQueue = null;
private List<PoolThread> threads = new ArrayList<PoolThread>();
private boolean isStopped = false;
public ThreadPool(int noOfThreads, int maxNoOfTasks){
taskQueue = new BlockingQueue(maxNoOfTasks);
for(int i=0; i<noOfThreads; i++){
threads.add(new PoolThread(taskQueue));
}
for(PoolThread thread : threads){
thread.start();
}
}
public synchronized void execute(Runnable task) throws Exception{
if(this.isStopped) throw
new IllegalStateException("ThreadPool is stopped");
this.taskQueue.enqueue(task);
}
public synchronized void stop(){
this.isStopped = true;
for(PoolThread thread : threads){
thread.doStop();
}
}
}
public class PoolThread extends Thread {
private BlockingQueue taskQueue = null;
private boolean isStopped = false;
public PoolThread(BlockingQueue queue){
taskQueue = queue;
}
public void run(){
while(!isStopped()){
try{
Runnable runnable = (Runnable) taskQueue.dequeue();
runnable.run();
} catch(Exception e){
//log or otherwise report exception,
//but keep pool thread alive.
}
}
}
public synchronized void doStop(){
isStopped = true;
this.interrupt(); //break pool thread out of dequeue() call.
}
public synchronized boolean isStopped(){
return isStopped;
}
}
(校注:原文有编译错误,我修改了下)
public class PoolThread extends Thread {
private BlockingQueue<Runnable> taskQueue = null;
private boolean isStopped = false;
public PoolThread(BlockingQueue<Runnable> queue) {
taskQueue = queue;
}
public void run() {
while (!isStopped()) {
try {
Runnable runnable =taskQueue.take();
runnable.run();
} catch(Exception e) {
// 写日志或者报告异常,
// 但保持线程池运行.
}
}
}
public synchronized void toStop() {
isStopped = true;
this.interrupt(); // 打断池中线程的 dequeue() 调用.
}
public synchronized boolean isStopped() {
return isStopped;
}
}
线程池的实现由两部分组成。类ThreadPool是线程池的公开接口,而类PoolThread用来实现执行任务的子线程。
为了执行一个任务,方法ThreadPool.execute(Runnable r)用Runnable的实现作为调用参数。在内部,Runnable对象被放入阻塞队列 (Blocking Queue),等待着被子线程取出队列。
一个空闲的PoolThread线程会把Runnable对象从队列中取出并执行。你可以在PoolThread.run()方法里看到这些代码。执行完毕后,PoolThread进入循环并且尝试从队列中再取出一个任务,直到线程终止。
调用ThreadPool.stop()方法可以停止ThreadPool。在内部,调用stop先会标记isStopped成员变量(为 true)。然后,线程池的每一个子线程都调用PoolThread.stop()方法停止运行。注意,如果线程池的execute()在stop()之后调用,execute()方法会抛出IllegalStateException异常。
子线程会在完成当前执行的任务后停止。注意PoolThread.stop()方法中调用了this.interrupt()。它确保阻塞在taskQueue.dequeue()里的wait()调用的线程能够跳出wait()调用(校对注:因为执行了中断interrupt,它能够打断这个调用),并且抛出一个InterruptedException异常离开dequeue()方法。这个异常在PoolThread.run()方法中被截获、报告,然后再检查isStopped变量。由于isStopped的值是true, 因此PoolThread.run()方法退出,子线程终止。
(校对注:看完觉得不过瘾?更详细的线程池文章参见Java线程池的分析和使用)
26、Java并发性和多线程-线程池的更多相关文章
- 15、Java并发性和多线程-线程通讯
以下内容转自http://ifeve.com/thread-signaling/: 线程通信的目标是使线程间能够互相发送信号.另一方面,线程通信使线程能够等待其他线程的信号. 例如,线程B可以等待线程 ...
- 10、Java并发性和多线程-线程安全与不可变性
以下内容转自http://ifeve.com/thread-safety-and-immutability/: 当多个线程同时访问同一个资源,并且其中的一个或者多个线程对这个资源进行了写操作,才会产生 ...
- 9、Java并发性和多线程-线程安全与共享资源
以下内容转自http://ifeve.com/thread-safety/: 允许被多个线程同时执行的代码称作线程安全的代码.线程安全的代码不包含竞态条件.当多个线程同时更新共享资源时会引发竞态条件. ...
- java 并发性和多线程 -- 读感 (一 线程的基本概念部分)
1.目录略览 线程的基本概念:介绍线程的优点,代价,并发编程的模型.如何创建运行java 线程. 线程间通讯的机制:竞态条件与临界区,线程安全和共享资源与不可变性.java内存模型 ...
- Java并发性和多线程
Java并发性和多线程介绍 java并发性和多线程介绍: 单个程序内运行多个线程,多任务并发运行 多线程优点: 高效运行,多组件并行.读->操作->写: 程序设计的简单性,遇到多问题, ...
- Java并发性和多线程介绍
java并发性和多线程介绍: 单个程序内运行多个线程,多任务并发运行 多线程优点: 高效运行,多组件并行.读->操作->写: 程序设计的简单性,遇到多问题,多开线程就好: 快速响应,异步式 ...
- Java 并发和多线程(一) Java并发性和多线程介绍[转]
作者:Jakob Jenkov 译者:Simon-SZ 校对:方腾飞 http://tutorials.jenkov.com/java-concurrency/index.html 在过去单CPU时 ...
- Java高级教程:Java并发性和多线程
Java并发性和多线程: (中文,属于人工翻译,高质量):http://ifeve.com/java-concurrency-thread-directory/ (英文):http://tutoria ...
- Java并发(六)线程池监控
目录 一.线程池监控参数 二.线程池监控类 三.注意事项 在上一篇博文中,我们介绍了线程池的基本原理和使用方法.了解了基本概念之后,我们可以使用 Executors 类创建线程池来执行大量的任务,使用 ...
随机推荐
- 支持多种格式的播放器js代码
FLV需要播放器,其它视频格式直接插入相应的代码即可. ------------------------------------- /** *视频播放 by zhensheng@ *参数说明 ...
- Mysql动态查询
if条件查询 格式: <if test=”条件判断”> 添加到sql的语句 </if> where标签 简化SQL语句中WHERE条件判断 智能处理and和or 如果使用几个i ...
- [ GDOI 2014 ] 拯救莫莉斯
\(\\\) \(Description\) 有一个 \(N\times M\) 的网格,每个格点都有权值,图是四连通的. 现在选择一个点集,使得每个格点要么被选中,要么连通的点之一被选中. 求这个点 ...
- Android 知识Tips
有一些Android很小的知识点,不值得单独写出来做为一篇博客.都在这个博客里面进行总结 1.ImageButton控件,中间图片的放置效果可以用scaleType来设置,如下: <ImageB ...
- JavaScript设计模式 (1) 原型模式
原型模式(Prototype):用原型实例指向创建类对象,使用于创建新对象的类共享原型对象的属性以及方法. //图片轮播类 var LoopImages = function (imgArr, con ...
- centos上安装supervisor来管理dotnetcore等应用程序
supervisor 介绍: 这是一款用python编写的进程管理工具,可以守护他管理的所有进程,防止异常退出,以及提供一个可视化的web界面来手动管理,打开关闭重启各种应用,界面如下: 关于在cen ...
- poi导出word时设置兼容性
接上一篇poi导出word http://www.cnblogs.com/xiufengd/p/4708680.html. public static void setAuto(XWPFDocumen ...
- HDU_3591_(多重背包+完全背包)
The trouble of Xiaoqian Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/ ...
- GetArxPath
extern HINSTANCE _hdllInstance;CString GetArxPath(){ CString strArxPath; GetModuleFileName(_hdllInst ...
- HDU多校Round 8
Solved:2 rank:141 D. Parentheses Matrix n,m有一个小于6的时候是一种构造方法 答案是n + (m - 2) / 2 (n > m) 都大于6的时候 可以 ...