I spotted that I can use the combination of the following two methods on ThreadPoolExecutor:
That's great. Since after these two methods, the main thread can ensure all the threads in the pool have completed.
However, after the shutdown(), there is no way that you can add another task into the pool. (The pool is considered to be closed and shutdown). Where is the restart() method on the pool, I wonder.
The only workaround I found is to create a new instance of the ThreadPoolExecutor like the code below.
exec = (ThreadPoolExecutor)Executors.newCachedThreadPool();
Can anybody advise if this is a good practice to use ThreadPoolExecutor? It seems that everytime I perform a shutdown and awaitTermination, I need to create a new instance of ThreadPoolExecutor. I smells bad code.
Mike Simmons wrote:For your use case, I think it would be better to use invokeAll(), which will block until all tasks in the Collection you pass in have been completed or cancelled. That way you don't have to keep creating a whole new ThreadPoolExecutor for each set of tasks you need to wait for.
Thanks for your reply. However, invokeAll() does not suit my case. As soon as a task is added (submitted) into the TPE, I hope to start it immediately. I do not wait for another tasks to be added before starting these threads.
Now I think I have another solution to wait for all the running threads in the TPE, *without* shutting down the TPE and re-instantiate another instance of TPE.
Every time I add a new task into the TPE, I maintain a hashmap like below:
And if I want to wait for all the running threads to complete, I simply need to invoke the get() method on all the Future object like below:
The nature of the get() method waits for the thread to complete and get the result if necessary. (In my case, I don't have any return values). This definitely look like a better solution.