1.背景
诸如Web 服务器、数据库服务器、文件服务器或邮件服务器之类的许多服务器应用程序都面向处理来自某些远程来源的大量短小的任务。 服务器应用程序中经常出现的情况是:单个任务处理的时间很短而请求的数目却是巨大的。
2.解决方法
构建服务器应用程序的一个过于简单的模型应该是:每当一个请求到达就创建一个新线程,然后在新线程中为请求服务。
那么这种方法的严重不足就很明显。每个请求对应一个线程(thread-per-request)方法的不足之一是:为每个请求创建一个新线程的开销很大;在一个 JVM 里创建太多的线程可能会导致系统由于过度消耗内存而用完内存或“切换过度”。为了防止资源不足,服务器应用程序需要一些办法来限制任何给定时刻处理的请求数目。
我们可以实现一个线程池类,其中客户机类等待一个可用线程、将任务传递给该线程以便执行、然后在任务完成时将线程归还给池,一般一个简单线程池至少包含下列组成部分:
线程池管理器(ThreadPoolManager):用于创建并管理线程池
工作线程(WorkThread): 线程池中线程
任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。
任务队列:用于存放没有处理的任务。提供一种缓冲机制。
publicclass WorkQueue
{
private final int nThreads;
private final PoolWorker[] threads;
private final LinkedList queue;
public WorkQueue(int nThreads) {
this.nThreads = nThreads;
queue = new LinkedList();
threads = new PoolWorker[nThreads];
for (int i = 0; i < nThreads; i++) {
threads[i] = new PoolWorker();
threads[i].start();
}
}
public void execute(Runnable r) {
synchronized (queue) {
queue.addLast(r);
queue.notify();
}
}
private class PoolWorker extends Thread {
public void run() {
Runnable r;
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
try {
queue.wait();
} catch(InterruptedException ignored) {
}
}
r = (Runnable)queue.removeFirst();
}
// If we don't catchRuntimeException,
// the pool could leak threads
try {
r.run();
} catch (RuntimeException e) {
// You might want to logsomething here
}
}
}
}
public static void main(String args[]) {
WorkQueue wq = new WorkQueue(3);
wq.execute(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++){
try {
Thread.sleep(1000);
} catch (Exception e) {}
System.out.println("this is a thread");
}
}
});
}
}