ThreadPoolExecutor的使用
一个 ExecutorService,它使用可能的几个池线程之一执行每个提交的任务,通常使用 Executors 工厂方法配置。
线程池可以解决两个不同问题:由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行集合任务时使用的线程)的方法。每个 ThreadPoolExecutor 还维护着一些基本的统计数据,如完成的任务数。
下面是一个简单的例子,详细用法大家还是要查下API……
[ThreadPoolExecutorDemo]
创建了一个队列用于存放数据(整型)和一个线程池,
一开始填满队列,并启动5个线程来执行任务。
-
import java.util.concurrent.*;
-
-
public class ThreadPoolExecutorDemo {
-
-
static BlockingQueue<Integer> warehouse = new ArrayBlockingQueue<Integer>(100);
-
-
static ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 10, // 核心线程数:池中所保存的线程数,包括空闲线程
-
20, // 池中允许的最大线程数
-
1, // 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间
-
TimeUnit.SECONDS, // keepAliveTime 参数的时间单位
-
new LinkedBlockingQueue(20)
-
// 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。
-
);
-
-
// 预备数据:填满整个队列
-
for(int i=0; warehouse.remainingCapacity()>0; i++){
-
warehouse.offer(i);
-
}
-
-
// 线程池执行:
-
for(int i=0; i<5; i++){
-
threadPool.execute(new PrintIntThread(warehouse));
-
}
-
-
// 令这些任务都执行完后关闭线程池
-
threadPool.shutdown();
-
}
-
-
}
[PrintIntThread]
该类实现了Runnable接口,目的是处理任务。
当数据未取完时一直取数据。(这里为了观察方便,定义每次取完后休息一段时间)
-
import java.util.concurrent.BlockingQueue;
-
-
-
-
static BlockingQueue<Integer> warehouse;
-
-
public PrintIntThread(BlockingQueue<Integer> warehouse) {
-
this.warehouse = warehouse;
-
}
-
-
public void run() {
-
while(warehouse.size()>0){
-
try {
-
e.printStackTrace();
-
}
-
}
-
}
-
-
}
* 注意
· 线程池要记得关闭,若没有shutdown则应用程序不会停止……
· 若启动的线程小于核心线程数,则线程池会自动创建新线程,即使空闲着。
· 若当前线程数大于核心线程数,当一个线程空闲时间超过定义的时间时线程池会自动终止该线程。
· 每次提交任务,线程池分配给空闲线程,若没有则存放到任务队列中,队列已满时线程池才创建新线程去处理任务(按需构造),但若当前线程数已达到线程池最大应许线程数时则任务会被拒绝。任务队列有好几种,大家自己看API……