其实线程池的实现就是生产者消费者问题 的实现,理解了生产者消费者问题 就不会对线程池的实现感到神秘了,线程池在很多地方会用到,比如 tomcat 等各种中间容器的实现, Spring 对线程池的支持等,当然 mina 中也使用到了线程池的概念。
看下简单对线程池的实现代码,主要包括三个类,一个是线程池,一个是工作任务,一个是客户端进行任务添加。
任务类,比较简单,实现 Runnable 接口:
//任务类,具体要执行的操作
public class Worker implements Runnable {
private int id;
public Worker(int id) {
this.id = id;
}
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程:" + Thread.currentThread().getName() + " 执行任务" + id);
}
}
线程池,相对复杂一些,但是原理是很简单的:
public class ThreadPool {
// 线程池大小
private final int nThreads;
// 线程池工作者(具体线程)
private final PoolWorker[] threads;
// 任务队列
private final LinkedList<Runnable> queue;
public ThreadPool(int nThreads) {
// 初始线程池,并启动线程池里面的线程
this.nThreads = nThreads;
queue = new LinkedList<Runnable>();
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 = queue.removeFirst();
}
try {
r.run();
} catch (RuntimeException e) {
}
}
}
}
}
客户端代码:
public class Client {
public static void main(String[] args) {
ThreadPool queue = new ThreadPool(10);
// 提交工作任务。
queue.execute(new Worker(1));
queue.execute(new Worker(2));
queue.execute(new Worker(3));
}
}
线程池实现其实比较简单的,但是实际应用中我们用线程池比较常见的方式还是使用 JDK 中对线程池的实现,它提供了 ExecutorService , Executor 等类实现了对线程池的支持,不过线程池的实现原理其实是和我们的一样的,只不过它更多的考虑了实现细节,功能更强一些,关于它的使用网上有很多文章讲的已经很清楚了,可以参考: http://mshijie.iteye.com/blog/366591