多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。
假设一个服务器完成一项任务所需时间为:T1
创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。
如果:T1
+ T3 远大于 T2,则可以采用线程池,以提高服务器性能。
一个线程池包括以下四个基本组成部分:
1、线程池管理器(ThreadPool):用于创建并管理线程池,包括
创建线程池,销毁线程池,添加新任务;
2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性能的。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。
线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目,看一个例子:
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class FixedThreadPoolDemo {
public static void main(String[] args) {
// 创建一个最多同时运行 3 个任务的线程池
ExecutorService service = Executors.newFixedThreadPool(3);
// 安排若干个任务运行
service.execute(new RunnableImpl(1));
service.execute(new RunnableImpl(2));
service.execute(new RunnableImpl(3));
service.execute(new RunnableImpl(4));
service.execute(new RunnableImpl(5));
service.execute(new RunnableImpl(6));
service.execute(new RunnableImpl(7));
service.execute(new RunnableImpl(8));
service.execute(new RunnableImpl(9));
service.execute(new RunnableImpl(10));
service.execute(new RunnableImpl(11));
service.execute(new RunnableImpl(12));
service.execute(new RunnableImpl(13));
service.execute(new RunnableImpl(14));
service.execute(new RunnableImpl(15));
// 结束线程池。shutdown() 不会马上结束,而是等所有安排的任务执行完才结束。
service.shutdown();
// 如果不想马上结束,又不愿意等太长时间,那么可以调用 awaitTermination() 方法等待一段时间
try {
service.awaitTermination(5, TimeUnit.SECONDS);
System.err.println("等待时间已过");
// shutdownNow() 将放弃所有正在等待的任务,等当前执行的任务全部完成之后,结束线程池。
List<Runnable> abandoned = service.shutdownNow();
System.err.println("被遗弃的任务:" + abandoned);
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(-1);
}
}
private static class RunnableImpl implements Runnable {
private int id;
private RunnableImpl(int id) {
this.id = id;
}
public void run() {
System.out.println("开始执行" + id);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// nothing to do
}
System.out.println(id + "执行完毕。");
}
@Override
public String toString() {
return "线程" + id;
}
}
}