private WorkerThread<inType, outType> getOptimalThread() {
		WorkerThread<inType, outType> min = null;
		final boolean threadPoolFull = (threadPool.size() >= maxThreads);

		for (WorkerThread<inType, outType> t : threadPool.keySet()) {
			if (t.isWaiting())
				return t;

			// if the pool is full (we can't add) and either
			// ( min hasn't been set ) OR ( this is a thread with a smaller
			// queue)
			else if (threadPoolFull
					&& (min == null || min.inQueue.size() > t.inQueue.size()))
				min = t;
		}

		if (threadPoolFull)
			return min;
		else { // add a new thread
			WorkerThread<inType, outType> w = threadTemplate.clone();
			Thread t = new Thread(w);
			threadPool.put(w, t);
			t.start();

			return w;
		}
	}