线程池是大多数服务器软件都应当实现的功能,在Java中创建线程是一个比较耗资源的操作,不仅占用Java虚拟机的资源,还占用操作系统的资源。然而大多数服务器线程执行过程都很短暂,以Web服务器为例,每个HTTP请求通常在几个毫秒内就完成了,如果频繁地创建,撤消线程会使系统效率下降。
要实现线程池也很简单,即当线程操作完成时并不立即撤消它,而是将它转入一种休眠状态,当新的操作要执行时再将其唤醒。“休眠”与“唤醒”是通过Java的同步元语synchronized, notify, wait来完成的,虽然Java的同步机制很简单,但如果使用的当能够实现很多复杂的并发处理算法,当然,编写多线程程序是很让人头疼的,如果你对这方面不是很了解最好不要急着去尝试。
下面是一个完整的线程池的实现,你可以用在自己的程序中,Apusic的线程池比这个要复杂一些,但基本原理差不多。
import java.util.LinkedList;
public class ThreadPool
{
static final long IDLE_TIMEOUT = 60000L;
private String name;
private int minsize;
private int maxsize;
private int nextWorkerId = 0;
private LinkedList pool = new LinkedList();
public ThreadPool() {
this("PooledThread");
}
public ThreadPool(String name) {
this(name, 0, 20);
}
public ThreadPool(String name, int minsize, int maxsize) {
this.name = name;
this.minsize = minsize;
this.maxsize = maxsize;
}
public synchronized void run(Runnable runner) {
Worker worker;
if (runner == null) {
throw new NullPointerException();
}
// get a worker from free list...
if (!pool.isEmpty()) {
worker = (Worker) pool.removeFirst();
} else {
// ...no free worker available, create new one...
worker = new Worker(name + "-" + ++nextWorkerId);
worker.start();
}
// ...and wake up worker to service incoming runner
worker.wakeup(runner);
}
// Notified when a worker has idled timeout
// @return true if worker should die, false otherwise
synchronized boolean notifyTimeout(Worker worker) {
if (worker.runner != null) {
return false;
}
if (pool.size() > minsize) {
// Remove from free list
pool.remove(worker);
return true; // die
}
return false; // continue
}
// Notified when a worker has finished his work and
// free to service next runner
// @return true if worker should die, false otherwise
synchronized boolean notifyFree(Worker worker) {
if (pool.size() < maxsize) {
// Add to free list
pool.addLast(worker);
return false; // continue
}
return true; // die
}
// The inner class that implement worker thread
class Worker extends Thread {
Runnable runner = null;
public Worker(String name) {
super(name);
}
synchronized void wakeup(Runnable runner) {
this.runner = runner;
notify();
}
public void run() {
for (;;) {
synchronized (this) {
if (runner == null) {
try {
wait(IDLE_TIMEOUT);
} catch (InterruptedException e) {}
}
}
// idle timed out, die or put into free list
if (runner == null) {
if (notifyTimeout(this))
return;
else
continue;
}
try {
runner.run();
} finally {
runner = null;
if (notifyFree(this))
return;
}
}
}
}
}
线程池用一个双向链表来表示,池中的元素是处于休眠状态的工作线程。ThreadPool类大部分工作都是来维护这个双向链表,当有新的请求到达时,先从表头摘取一个工作线程,将其唤醒转入工作状态。如果线程池为空,则创建一个新的工作线程。当线程工作完成时调用notifyFree将线程归还到线程池中,并通知线程进入休眠状态。程序中设置了一个IDLE_TIMEOUT超时值,如果线程处于休眠状态的时间超过了这个值,则将线程消灭。当使用线程池时不必直接使用Thread对象,而是创建一个实现了Runnable接口的对象,调用ThreadPool.run()来运行线程,实际的线程运行过程有内部类Worker来完成。
下面是使用线程池的程序片段:
class TestRunner implements Runnable {
public void run() {
// ... put your operations here
}
}
ThreadPool pool = new ThreadPool();
TestRunner r = new TestRunner();
pool.run(r);
要实现线程池也很简单,即当线程操作完成时并不立即撤消它,而是将它转入一种休眠状态,当新的操作要执行时再将其唤醒。“休眠”与“唤醒”是通过Java的同步元语synchronized, notify, wait来完成的,虽然Java的同步机制很简单,但如果使用的当能够实现很多复杂的并发处理算法,当然,编写多线程程序是很让人头疼的,如果你对这方面不是很了解最好不要急着去尝试。
下面是一个完整的线程池的实现,你可以用在自己的程序中,Apusic的线程池比这个要复杂一些,但基本原理差不多。
import java.util.LinkedList;
public class ThreadPool
{
static final long IDLE_TIMEOUT = 60000L;
private String name;
private int minsize;
private int maxsize;
private int nextWorkerId = 0;
private LinkedList pool = new LinkedList();
public ThreadPool() {
this("PooledThread");
}
public ThreadPool(String name) {
this(name, 0, 20);
}
public ThreadPool(String name, int minsize, int maxsize) {
this.name = name;
this.minsize = minsize;
this.maxsize = maxsize;
}
public synchronized void run(Runnable runner) {
Worker worker;
if (runner == null) {
throw new NullPointerException();
}
// get a worker from free list...
if (!pool.isEmpty()) {
worker = (Worker) pool.removeFirst();
} else {
// ...no free worker available, create new one...
worker = new Worker(name + "-" + ++nextWorkerId);
worker.start();
}
// ...and wake up worker to service incoming runner
worker.wakeup(runner);
}
// Notified when a worker has idled timeout
// @return true if worker should die, false otherwise
synchronized boolean notifyTimeout(Worker worker) {
if (worker.runner != null) {
return false;
}
if (pool.size() > minsize) {
// Remove from free list
pool.remove(worker);
return true; // die
}
return false; // continue
}
// Notified when a worker has finished his work and
// free to service next runner
// @return true if worker should die, false otherwise
synchronized boolean notifyFree(Worker worker) {
if (pool.size() < maxsize) {
// Add to free list
pool.addLast(worker);
return false; // continue
}
return true; // die
}
// The inner class that implement worker thread
class Worker extends Thread {
Runnable runner = null;
public Worker(String name) {
super(name);
}
synchronized void wakeup(Runnable runner) {
this.runner = runner;
notify();
}
public void run() {
for (;;) {
synchronized (this) {
if (runner == null) {
try {
wait(IDLE_TIMEOUT);
} catch (InterruptedException e) {}
}
}
// idle timed out, die or put into free list
if (runner == null) {
if (notifyTimeout(this))
return;
else
continue;
}
try {
runner.run();
} finally {
runner = null;
if (notifyFree(this))
return;
}
}
}
}
}
线程池用一个双向链表来表示,池中的元素是处于休眠状态的工作线程。ThreadPool类大部分工作都是来维护这个双向链表,当有新的请求到达时,先从表头摘取一个工作线程,将其唤醒转入工作状态。如果线程池为空,则创建一个新的工作线程。当线程工作完成时调用notifyFree将线程归还到线程池中,并通知线程进入休眠状态。程序中设置了一个IDLE_TIMEOUT超时值,如果线程处于休眠状态的时间超过了这个值,则将线程消灭。当使用线程池时不必直接使用Thread对象,而是创建一个实现了Runnable接口的对象,调用ThreadPool.run()来运行线程,实际的线程运行过程有内部类Worker来完成。
下面是使用线程池的程序片段:
class TestRunner implements Runnable {
public void run() {
// ... put your operations here
}
}
ThreadPool pool = new ThreadPool();
TestRunner r = new TestRunner();
pool.run(r);