Java cachedThreadPool kill submitted threads
I need to do multi-threaded work and I use ExecutorService.newCachedThreadPool()
and post some job received from the queue.
public class ContentParser {
public static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
// ...
public static void queueExecutor(Content content) {
String url = "";
while ((url = queue.poll()) != null){
LOG.info("Picked url " + url);
cachedThreadPool.submit(new ParserCallable(content, url));
}
}
// ...
private static class ParserCallable implements Runnable {
private Content content;
private String url;
private ParserCallable(Content content, String url) {
this.url = url;
this.content = content;
}
@Override
public void run(){
new FontParser().fontSearcher(content, url);
}
}
This way each thread creates a new instance FontParser
, and inside it I do some work.
I call mine ContentParser.queueExecutor
from another class, so after submitting all assignments I do:
ContentParser.cachedThreadPool.shutdown();
ContentParser.cachedThreadPool.awaitTermination(5l, TimeUnit.MINUTES);
But it just kills my threads, even if the work is not finished and is not waiting.
Maybe because I am creating a new instance new FontParser().fontSearcher(content, url);
in each thread?
source to share
I am calling my ContentParser.queueExecutor from another class, so after submitting all the jobs, I do:
It looks like you are saying that someone is calling cachedThreadPool.shutdown()
, but jobs are still being submitted to the pool. This should never have happened. shutdown()
should only be called after the loop has finished poll()
.
I would recommend doing something like the following in your method queueExecutor(...)
:
while ((url = queue.poll()) != null){
LOG.info("Picked url " + url);
cachedThreadPool.submit(new ParserCallable(content, url));
}
// shutdown _after_ all jobs have been submitted
cachedThreadPool.shutdown();
Also, in general, it is bad practice to make fields public - especially in this case, your field cachedThreadPool
. You have no control over how (or in this case, when) external classes call critical methods in your pool. I would make it private and then the wait method in the class ContentParser
:
private static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
...
public static void awaitPoolTermination(/* maybe timeout args here */) {
cachedThreadPool.awaitTermination(5l, TimeUnit.MINUTES);
}
This better controls the thread pool and prevents you from shutting down in the wrong place. So the caller ContentParser
will call first contentParser.queueExecutor(...)
and then call contentParser.awaitPoolTermination(...)
.
source to share