有效地向Java ThreadPool提交无限数量的任务

时间:2018-11-26 15:30:28

标签: java multithreading threadpool executorservice threadpoolexecutor

我想知道什么是最好的设计模式: 我有无限的任务可以处理,每个任务的大小(问题大小)各不相同。为此,我创建了一个带有PriorityBlockingQueue的ThreadPool(2个核心池,4个最大池)。

每执行一次任务,它就会被优先添加到池中。当我有2个任务可能需要一段时间(例如10分钟)并且它们填满了核心池时,就会出现问题。因此,只要我尝试提交新任务,就可以使用 getTaskCount getCorePoolSize 检查它们何时仍在工作,然后将新任务添加到当前队列中。现在,当这两个任务花费很长时间(超过5、10、20分钟)时,会发生什么情况?我该如何接受可能需要1秒,3秒等才能完成的新任务?我需要为任务创建的每个可运行对象都设置一个超时时间,以确保其消失吗?

希望有人可以提供一些帮助。 谢谢!

1 个答案:

答案 0 :(得分:0)

如何使用这样的构造?

class Scratch {

    public static ExecutorService   pool    = Executors.newSingleThreadExecutor();
    public static AtomicInteger     runnableCount = new AtomicInteger();

    // Returns the next task that needs to run - insert your logic here
    // This method will be called whenever the previous Runnable is done
    public static Runnable getNextRunnable() {
        return () -> {
            System.out.println("Runnable " + runnableCount.incrementAndGet() + " Doing work");
            try {
                Thread.sleep(10); // Sleep to prevent runaway endless loop
            } catch (InterruptedException e) {
            }
        };
    }

    // Submits the next task to the pool, adds callback to add next task
    public static void submitNextRunnable(Void ignored) {
        CompletableFuture<Void> future = CompletableFuture.runAsync(getNextRunnable(), pool);
        future.thenAccept(Scratch::submitNextRunnable);
    }

    public static void main(String[] args) {
        submitNextRunnable(null);
    }
}

以上代码从创建一个Executor并提交一个Runnable开始。每当提交Runnable时,我们都会给它提供一个回调函数,该函数将在上一个函数完成时提交下一个Runnable。它是递归的。

该代码的输出是Runnables的无休止流,其中显示了它们的执行情况:

Runnable 1 Doing work
Runnable 2 Doing work
Runnable 3 Doing work
Runnable 4 Doing work
Runnable 5 Doing work
Runnable 6 Doing work
Runnable 7 Doing work
Runnable 8 Doing work
Runnable 9 Doing work
Runnable 10 Doing work
Runnable 11 Doing work
Runnable 12 Doing work
Runnable 13 Doing work
Runnable 14 Doing work

这样,您就不需要时间或轮询执行者的任务数量。每当上一个Runnable完成时,您只需获取一个回调。 如果要一次提交多个任务,只需多次拨打submitNextRunnable(null);