线程池,给予其任务执行,线程池本身又有线程的概念,所以现在就有三个实体,1个线程池,m个线程,n个任务,看程序:
import java.util.LinkedList; /** A thread pool is a group of a limited number of threads that are used to execute tasks. */ public class ThreadPool extends ThreadGroup { private boolean isAlive; private LinkedList taskQueue; private int threadID; private static int threadPoolID; /** Creates a new ThreadPool. @param numThreads The number of threads in the pool. */ public ThreadPool(int numThreads) { super("ThreadPool-" + (threadPoolID++)); setDaemon(true); isAlive = true; taskQueue = new LinkedList(); for (int i=0; i<numThreads; i++) { new PooledThread().start(); } } /** Requests a new task to run. This method returns immediately, and the task executes on the next available idle thread in this ThreadPool. <p>Tasks start execution in the order they are received. @param task The task to run. If null, no action is taken. @throws IllegalStateException if this ThreadPool is already closed. */ public synchronized void runTask(Runnable task) { if (!isAlive) { throw new IllegalStateException(); } if (task != null) { taskQueue.add(task); notify(); } } protected synchronized Runnable getTask() throws InterruptedException { while (taskQueue.size() == 0) { if (!isAlive) { return null; } wait(); } return (Runnable)taskQueue.removeFirst(); } /** Closes this ThreadPool and returns immediately. All threads are stopped, and any waiting tasks are not executed. Once a ThreadPool is closed, no more tasks can be run on this ThreadPool. */ public synchronized void close() { if (isAlive) { isAlive = false; taskQueue.clear(); interrupt(); } } /** Closes this ThreadPool and waits for all running threads to finish. Any waiting tasks are executed. */ public void join() { // notify all waiting threads that this ThreadPool is no // longer alive synchronized (this) { isAlive = false; notifyAll(); } // wait for all threads to finish Thread[] threads = new Thread[activeCount()]; int count = enumerate(threads); for (int i=0; i<count; i++) { try { threads[i].join(); } catch (InterruptedException ex) { } } } /** A PooledThread is a Thread in a ThreadPool group, designed to run tasks (Runnables). */ private class PooledThread extends Thread { public PooledThread() { super(ThreadPool.this, "PooledThread-" + (threadID++)); } public void run() { while (!isInterrupted()) { // get a task to run Runnable task = null; try { task = getTask(); } catch (InterruptedException ex) { } // if getTask() returned null or was interrupted, // close this thread by returning. if (task == null) { return; } // run the task, and eat any exceptions it throws try { task.run(); } catch (Throwable t) { uncaughtException(this, t); } } } } }
public class ThreadPoolTest { public static void main(String[] args) { if (args.length != 2) { System.out.println("Tests the ThreadPool task."); System.out.println( "Usage: java ThreadPoolTest numTasks numThreads"); System.out.println( " numTasks - integer: number of task to run."); System.out.println( " numThreads - integer: number of threads " + "in the thread pool."); return; } int numTasks = Integer.parseInt(args[0]); int numThreads = Integer.parseInt(args[1]); // create the thread pool ThreadPool threadPool = new ThreadPool(numThreads); // run example tasks for (int i=0; i<numTasks; i++) { threadPool.runTask(createTask(i)); } // close the pool and wait for all tasks to finish. threadPool.join(); } /** Creates a simple Runnable that prints an ID, waits 500 milliseconds, then prints the ID again. */ private static Runnable createTask(final int taskID) { return new Runnable() { public void run() { System.out.println("Task " + taskID + ": start"); // simulate a long-running task try { Thread.sleep(500); } catch (InterruptedException ex) { } System.out.println("Task " + taskID + ": end"); } }; } }
总体流程如下:
1. 创建一个带m个线程的线程池
// create the thread pool ThreadPool threadPool = new ThreadPool(numThreads);
注意新建线程池的时候,其内部线程就已经启动了
for (int i=0; i<numThreads; i++) { new PooledThread().start(); }
每个线程的工作类似,都是获取任务并执行任务内容,但任务未分配到位,就进行阻塞,到位一个任务就得到一个任务并执行之
public synchronized void runTask(Runnable task) { if (!isAlive) { throw new IllegalStateException(); } if (task != null) { taskQueue.add(task); notify(); } } protected synchronized Runnable getTask() throws InterruptedException { while (taskQueue.size() == 0) { if (!isAlive) { return null; } wait(); } return (Runnable)taskQueue.removeFirst(); }
到这里也许会想,非要分配一个任务,获取一个任务再执行一个任务这种工作模式吗,我就不能一下分配所有任务后,一下获取,然后全部执行吗?我想可以肯定是可以的,但无论哪种方式,都必须解决一个有序获取任务的问题,否则造成n个线程争一个任务就不太好了,而现在等待的线程中会随机取一个线程分配其任务,就避免了无序争抢的问题
2. 给线程池分配n个任务
// run example tasks for (int i=0; i<numTasks; i++) { threadPool.runTask(createTask(i)); }
值得一提的是,既然是分配任务,这里为什么要写成runTask方法名呢,原因在于之前那些工作线程都已经启动了,只是因为没有任务而都被阻塞着,只要任务分配到位就会继续工作,因此在这里分配任务也就意味着启动了执行任务的开关,因此命名为runTask也是顺理成章的~