1 // Copyright 2000-2009 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
12 * - Attempting to add a task will block until the task is assigned to
14 * - If a task has not been assigned after MINIMUM_DISPATCH_DELAY, a new
15 * thread (above and beyond the ThreadPool size) will be created to
17 * - Whenever at least minIdleThreads are idle and more than minThreads
18 * threads exist overall, any threads which complete their task will
21 * Locking order: never attempt to acquire a lock on a PooledThread
22 * while holding the ThreadPool lock.
24 public final class ThreadPool {
26 private static final int MINIMUM_DISPATCH_DELAY = 1000;
27 private static final int minIdleThreads = 3;
29 private final int minThreads;
30 private int numThreads;
31 private final PooledThread[] idleThreads;
32 private int numIdleThreads;
34 public ThreadPool(int minThreads) {
35 this.minThreads = minThreads;
36 this.numThreads = minThreads;
37 this.numIdleThreads = 0;
38 this.idleThreads = new PooledThread[minThreads];
39 for(int i=0; i<this.idleThreads.length; i++)
43 public void start(Runnable r) {
44 synchronized(ThreadPool.this) {
45 /* if no idle threads, wait for MINIMUM_DISPATCH_DELAY or until notified */
46 if (numIdleThreads == 0) try {
47 this.wait(MINIMUM_DISPATCH_DELAY);
48 } catch (Exception e) { Log.error(this, e); }
50 /* if there are idle threads, use one */
51 if (numIdleThreads > 0) {
53 idleThreads[numIdleThreads].start(r);
54 idleThreads[numIdleThreads] = null;
57 /* otherwise, create a new thread */
60 new PooledThread().start(r);
63 private class PooledThread extends Thread {
64 private Runnable runnable = null;
65 public PooledThread() { start(); }
66 void start(Runnable runnable) {
68 if (this.runnable != null)
69 throw new Error("start() on a thread that is alread busy!");
70 this.runnable = runnable;
79 synchronized(ThreadPool.this) {
80 /* if the idle array is full, just let ourselves die */
81 if (numIdleThreads > minIdleThreads && numThreads > minThreads) return;
82 /* otherwise put ourselves back in the pool and release anybody who is waiting */
83 idleThreads[numIdleThreads++] = this;
84 ThreadPool.this.notifyAll();
89 synchronized(this) { while (runnable==null) wait(); }
91 synchronized(this) { runnable = null; }
92 } catch (Exception e) { Log.error(this, e); }
95 synchronized(ThreadPool.this) {