Эффективно отправлять бесконечное количество задач в Java ThreadPool - PullRequest
0 голосов
/ 26 ноября 2018

Я хотел бы знать, что является лучшим шаблоном проектирования для этого: у меня есть бесконечные задачи, которые я могу выполнить, каждая задача имеет различный размер (размер проблемы).Для этого я создал ThreadPool (2 основных пула, 4 максимальных пула) с PriorityBlockingQueue.

Всякий раз, когда я выполняю задачу, она добавляется в пул с приоритетом.Проблема возникает, когда у меня есть 2 задачи, которые могут занять некоторое время (скажем, 10 минут, например), и они заполняют основной пул.Поэтому, всякий раз, когда я пытаюсь отправить новую задачу, я могу проверить, когда они все еще находятся на работе, используя getTaskCount и getCorePoolSize , а затем добавить новую задачу в текущую очередь.Теперь, что происходит, когда две задачи занимают очень много времени (более 5, 10, 20 минут). Как я могу принять новые задачи, которые могут занять 1 секунду, 3 секунды ... и т. Д.?Нужно ли устанавливать тайм-аут на каждый исполняемый файл, который я создаю для своей задачи, чтобы убедиться, что он умирает?

надеюсь, что кто-то может дать какую-то дополнительную руку.спасибо!

1 Ответ

0 голосов
/ 26 ноября 2018

Как насчет использования такой конструкции?

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); несколько раз.

...