Thread Pools are useful when you need to limit the number of threads running in your application at the same time. There is a performance overhead associated with starting a new thread, and each thread is also allocated some memory for its stack etc.
线程池在当你需要在你的应用中同时运行多个线程时是有用的。开启新线程有性能开销,并且每个线程会分配一些栈内存。
Instead of starting a new thread for every task to execute concurrently, the task can be passed to a thread pool. As soon as the pool has any idle threads the task is assigned to one of them and executed. Internally the tasks are inserted into a Blocking Queue which the threads in the pool are dequeuing from. When a new task is inserted into the queue one of the idle threads will dequeue it successfully and execute it. The rest of the idle threads in the pool will be blocked waiting to dequeue tasks.
与每个任务开启一个线程并发执行不同,任务可以传递到线程池。当线程池有任何一个空闲线程,这个任务就可以被分配一个线程并执行。在内部,任务被插入到一个阻塞队列中,线程池中的线程可以从中出列(任务)。当一个新任务被添加到对列中,一个空闲线程将成功地获取并执行。其他的线程池中的空闲线程将被阻塞等待出列任务。
Thread pools are often used in multi threaded servers. Each connection arriving at the server via the network is wrapped as a task and passed on to a thread pool. The threads in the thread pool will process the requests on the connections concurrently. A later trail will get into detail about implementing multithreaded servers in Java.
线程池经常被用在多线程服务器中使用。每个通过网络到达服务器的连接都被封装为一个任务并传递到线程池中。线程池中的线程将并发地处理连接请求。接下来将详细介绍通过java实现多线程服务器。
Java 5 comes with built in thread pools in the java.util.concurrent package, so you don’t have to implement your own thread pool. You can read more about it in my text on the java.util.concurrent.ExecutorService. Still it can be useful to know a bit about the implementation of a thread pool anyways.
在Java5自带内建线程池在java.util.concurrent包中,所以你不必自己实现自己的线程池。你可以了解更多信息在我的java.util.concurrent.ExecutorService.一文中。不管怎样,了解一些线程池的实现是有用的。
Here is a simple thread pool implementation. Please note that this implementation uses my own BlockingQueue class as explained in my Blocking Queues tutorial. In a real life implementation you would probably use one of Java’s built-in blocking queues instead.
这里是一个简单的线程池实现。请注意该实现使用了我自己的 BlockingQueue类,在我的Blocking Queues 之旅中了解详情。在真实环境中你应该使用java内建的阻塞队列替换它。
public class ThreadPool {
private BlockingQueue taskQueue = null;
private List<PoolThread> threads = new ArrayList<PoolThread>();
private boolean isStopped = false;
public ThreadPool(int noOfThreads, int maxNoOfTasks){
taskQueue = new BlockingQueue(maxNoOfTasks);
for(int i=0; i<noOfThreads; i++){
threads.add(new PoolThread(taskQueue));
}
for(PoolThread thread : threads){
thread.start();
}
}
public synchronized void execute(Runnable task) throws Exception{
if(this.isStopped) throw
new IllegalStateException("ThreadPool is stopped");
this.taskQueue.enqueue(task);
}
public synchronized void stop(){
this.isStopped = true;
for(PoolThread thread : threads){
thread.doStop();
}
}
}
public class PoolThread extends Thread {
private BlockingQueue taskQueue = null;
private boolean isStopped = false;
public PoolThread(BlockingQueue queue){
taskQueue = queue;
}
public void run(){
while(!isStopped()){
try{
Runnable runnable = (Runnable) taskQueue.dequeue();
runnable.run();
} catch(Exception e){
//log or otherwise report exception,
//but keep pool thread alive.
}
}
}
public synchronized void doStop(){
isStopped = true;
this.interrupt(); //break pool thread out of dequeue() call.
}
public synchronized boolean isStopped(){
return isStopped;
}
}
The thread pool implementation consists of two parts. A ThreadPool class which is the public interface to the thread pool, and a PoolThread class which implements the threads that execute the tasks.
该线程池的实现是由两部分组成。ThreadPool是线程时的公共接口(这里的接口不是java中的接口,是对外使用的对接)PoolThread类实现执行任务的线程。
To execute a task the method ThreadPool.execute(Runnable r) is called with a Runnable implementation as parameter. The Runnable is enqueued in the blocking queue internally, waiting to be dequeued.
ThreadPool.execute(Runnable r)带有Runnable实现的方法 被调用去执行任务。这个Runnable在内部的阻塞队列中入列,等待出列。
The Runnable will be dequeued by an idle PoolThread and executed. You can see this in the PoolThread.run() method. After execution the PoolThread loops and tries to dequeue a task again, until stopped.
Runnable 将被一个空闲的PoolThread出列,执行,你可以在PoolThread.run()方法中看到。 执行完后(并不是线程执行完,其实是从阻塞队列获取任务后),PoolTread循环并试着再次出列一个任务,知道停止。
To stop the ThreadPool the method ThreadPool.stop() is called. The stop called is noted internally in the isStopped member. Then each thread in the pool is stopped by calling doStop() on each thread. Notice how the execute() method will throw an IllegalStateException if execute() is called after stop() has been called.
调用ThreadPool.stop()来停止线程。停止调用将在标记内部成员变量isStopped.线程池中的每个线程都可以调用各自的doStop()方法停止。注意,execute()方法将跑出IllegalStateException异常如果execute()方法在stop() 调用后调用。
The threads will stop after finishing any task they are currently executing. Notice the this.interrupt() call in PoolThread.doStop(). This makes sure that a thread blocked in a wait() call inside the taskQueue.dequeue() call breaks out of the wait() call, and leaves the dequeue() method call with an InterruptedException thrown. This exception is caught in the PoolThread.run() method, reported, and then the isStopped variable is checked. Since isStopped is now true, the PoolThread.run() will exit and the thread dies.
线程在完成它们并发完成的任务后将停止。注意this.interrupt()在PoolThread.doStop()中的调用。