性能优化中,其中一块是线程池的使用,初探线程池,从简单了解到源码分析,深入理解才能合理运用。
(一)线程池的来源及优点
单个异步任务,每次都需创建线程、销毁线程,当任务处理的时间短而请求数却巨大时,将导致资源消耗过多。
比如,数据库连接,需消耗大量资源,建立线程池能重用数据库访问线程。
使用线程池的优点:
1.降低资源消耗。重用现有线程,减少线程创建销毁开销。
2.提高响应速度。任务启动,无需经历线程创建,速度提升。
3.线程控制性强。如定时、定期、单线程设置等。
(二)线程池类别
四种线程池类型:
1.newCachedThreadPool
有缓存的线程池,适用于大量短期任务
2.newFixedThreadPool
定长的线程池,可控制最大线程并发数
3.newScheduledThreadPool
定长的线程池,可定时和周期性执行线程
4.newSingleThreadExecutor
单线程的线程池,保证所有任务按顺序执行
(三)线程池类别实例分析
1.newCachedThreadPool
private void newCacheThreadPool() {
ExecutorService threadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
final int index = i;
try {
if (i == 1 || i == 3) {
Thread.sleep(100);
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("new cached thread pool " + index + ":" +
Thread.currentThread().getId());
}
});
}
}
运行结果:
new cached thread pool 0:9
new cached thread pool 1:9
new cached thread pool 2:10
new cached thread pool 3:10
new cached thread pool 4:9
例子分析:因为1和3线程休息了一下,等待其他线程执行完,所以重用了旧有的线程。2.newFixedThreadPool
private void newFixedThreadPool() {
ExecutorService threadPool = Executors.newFixedThreadPool(2);
for (int i = 0; i < 5; i++) {
final int index = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("new fixed thread pool " + index + ":" +
Thread.currentThread().getId());
}
});
}
}
运行结果:
new fixed thread pool 0:9
new fixed thread pool 1:10
new fixed thread pool 2:9
new fixed thread pool 4:9
new fixed thread pool 3:10
例子分析:定长为2,其他线程进入队列,等待前俩线程执行完才运行。3.newScheduledThreadPool
private void newScheduledThreadPool() {
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(2);
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
e.printStackTrace();
}
threadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("new scheduled thread pool :" + Thread.currentThread().getId());
}
}, 1, 3, TimeUnit.SECONDS);
}
运行结果:
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
例子分析:延迟1秒开始,每隔3秒运行一次。
4.newSingleThreadExecutor
private void newSingleThreadPool() {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
final int index = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("new single thread pool " + index + ":" +
Thread.currentThread().getId());
}
});
}
}
运行结果:
new single thread pool 0:9
new single thread pool 1:9
new single thread pool 2:9
new single thread pool 3:9
new single thread pool 4:9
例子分析:只有单线程,所以,每次只能执行一个线程,其余任务等待状态。
一般来说,CachedTheadPool在程序执行过程中通常会创建与所需数量相同的线程,然后在它回收旧线程时停止创建新线程,因此它是合理的Executor的首选,只有当这种方式会引发问题时(比如需要大量长时间面向连接的线程时),才需要考虑用FixedThreadPool。(该段话摘自《Thinking in Java》第四版)
线程池源码分析请看java-线程池(二)