This solution assumes that processing occurs only on leaf nodes and that the actual tree recursion does not take much time.
I would call the thread of the calling thread, and then the BlockingQueue workers who process leaves through the thread pool. I do not handle InterruptedException in several places here.
public void processTree(TreeNode top) { final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(MAX_NUM_QUEUED); // create a pool that starts at 1 threads and grows to MAX_NUM_THREADS ExecutorService pool = new ThreadPoolExecutor(1, MAX_NUM_THREADS, 0L, TimeUnit.MILLISECONDS, queue, new RejectedExecutionHandler() { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { queue.put(r); // block if we run out of space in the pool } }); walkTree(top, pool); pool.shutdown(); // i think this will join with all of the threads pool.awaitTermination(WAIT_TILL_CHILDREN_FINISH_MILLIS, TimeUnit.MILLISECONDS); } private void walkTree(final TreeNode curr, ExecutorService pool) { if (curr.children == null || curr.children.isEmpty()) { pool.submit(new Runnable() { public void run() { processLeaf(curr); } }); return; } for (TreeNode child : curr.children) { walkTree(child, pool); } } private void processLeaf(TreeNode leaf) { // ... }
Gray
source share