线程池(Thread Pool)对于限制应用程序中同一时刻运行的线程数很有用。因为每启动一个新线程都会有相应的性能开销,每个线程都需要给栈分配一些内存等等。

我们可以把并发执行的任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程。只要池里有空闲的线程,任务就会分配给一个线程执行。在线程池的内部,任务被插入一个阻塞队列(Blocking Queue),线程池里的线程会去取这个队列里的任务。当一个新任务插入队列时,一个空闲线程就会成功的从队列中取出任务并且执行它。

线程池经常应用在多线程服务器上。每个通过网络到达服务器的连接都被包装成一个任务并且传递给线程池。线程池的线程会并发的处理连接上的请求。以后会再深入有关 Java 实现多线程服务器的细节。

Java 5 在 java.util.concurrent 包中自带了内置的线程池,所以你不用非得实现自己的线程池。

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 void synchronized execute(Runnable task) {
if(this.isStopped) throw
new IllegalStateException("ThreadPool is stopped"); this.taskQueue.enqueue(task);
} public synchronized boolean stop() {
this.isStopped = true;
for (PoolThread thread : threads) {
thread.stop();
}
} }

线程池的实现由两部分组成。类 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()方法退出,子线程终止。

最新文章

  1. 【WPF】最近在学习wpf 的绑定,,
  2. Switch能否用string做参数?
  3. iOS开发--应用设置及用户默认设置——转载
  4. sql概要
  5. MSDN 中 对vector::erase()的解释.xml
  6. homework-04 单词方阵
  7. 哪里有比较全的hadoop视频教程
  8. 【读书笔记】管道和FIFO
  9. #1042 - Can&#39;t get hostname for your address
  10. 一,ESP8266下载和刷固件
  11. Ruby on Rails 开发笔记
  12. P、NP、NPC、NP-Hard问题到底是何方神圣?
  13. react实现全选、取消全选和个别选择
  14. session的本质及如何实现共享?
  15. bootstrap学习笔记(网页开发小知识)
  16. em,rem区别比较
  17. 云服务的三种形式laas,paas,saas
  18. BZOJ 2756 SCOI2012 奇怪的游戏 最大流
  19. java_类型强转
  20. Leetcode--easy系列1

热门文章

  1. Clang Format
  2. iOS-----dSYM 文件分析工具
  3. 轻量级前端MVVM框架avalon - 模型转换
  4. DOM-Document类型
  5. JavaScript之自我总结篇
  6. 从一道面试题分析javascript闭包
  7. 基于DDD + SD.Framework实现的统一身份认证系统
  8. iOS对象属性详解
  9. 1Z0-053 争议题目解析520
  10. (3)MEF插件系统中通信机制的设计和实现