java cachedThreadPool杀死提交的线程

时间:2015-07-31 12:32:25

标签: java multithreading

我需要做一些多线程工作,并使用ExecutorService.newCachedThreadPool()并提交从队列中检索的一些作业。

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);
    }
}

因此每个线程都会创建一个FontParser的新实例,并且在其中我做了一些工作。

我从另一个班级打电话给我ContentParser.queueExecutor,所以在完成所有工作后我都会这样做:

ContentParser.cachedThreadPool.shutdown();
ContentParser.cachedThreadPool.awaitTermination(5l, TimeUnit.MINUTES);

但即使工作没有完成也不等待,它只会杀死我的线程。

也许是因为我在每个帖子中都创建了一个新实例new FontParser().fontSearcher(content, url);

1 个答案:

答案 0 :(得分:0)

  

我从另一个类调用我的ContentParser.queueExecutor,所以在提交所有作业之后我做了:

听起来你在说某人正在呼叫cachedThreadPool.shutdown()但是工作仍然被提交到池中。这绝不应该发生。只有在shutdown()循环完成后才应调用poll()

我建议您在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();

此外,一般情况下,将字段公开是一种不好的做法 - 尤其是在这种情况下,您的cachedThreadPool字段。您无法控制外部类在池上调用关键方法的方式(或在此情况下)。我将其设为私有,然后在ContentParser类上使用await方法:

private static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
...
public static void awaitPoolTermination(/* maybe timeout args here */) {
    cachedThreadPool.awaitTermination(5l, TimeUnit.MINUTES);
}

这样可以更好地控制您的线程池,并且不允许在不正确的位置关闭。因此,ContentParser方法的来电者先拨打contentParser.queueExecutor(...),然后拨打contentParser.awaitPoolTermination(...)