Принудительное повторное использование потока с помощью CompletableFuture - PullRequest
0 голосов
/ 07 февраля 2019

Я критически использую:

 CompletableFuture
  .delayedExecutor(1, TimeUnit.MILLISECONDS).execute(() -> {});

Из того, что я прочитал в Интернете, обычно для каждого вызова используется новая тема.Мне интересно, есть ли способ повторно использовать поток вместо создания новых потоков?

Обновление :

Мне было непонятно - я хочу использовать CompletableFuture, но я хочу CompletableFuture для повторного использования определенного потока вместо управления егособственные потоки.

Я вижу этот вопрос: CompletableFuture повторно использует поток из пула

, но рекомендует использовать переменную среды - мне интересно, есть ли способ сделать этопрограммным способом.

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Исходя из того, что я прочитал в Интернете, для каждого вызова характерно использование нового потока.

(1) Это имеет место, только если аппарат не поддерживает параллелизмили вы сделали это, чтобы не поддерживать его, установив системное свойство java.util.concurrent.ForkJoinPool.common.parallelism в 0 или 1.

8 процессоров

(2) Если машина поддерживает параллелизм, используется ForkJoinPool.commonPool() и уровень параллелизма устанавливается, я полагаю, в число доступных процессоров (которое можно определить с помощью Runtime#availableProcessors).

В сценарии с 8 процессорами, вероятно, будет создано 7-8 потоков для обслуживания общих ForkJoinPool.

Я хочу использовать CompletableFuture, но я хочу CompletableFuture для повторного использования определенного потока вместо управления его собственными потоками.

A DelayedExecutor просто передает задачи базовому Executor, который является либо ThreadPerTaskExecutor (1), либоForkJoinPool (2).

К счастью, вы можете вручную указать Executor, который будет использоваться DelayedExecutor для делегирования задач.

Executor delayedExecutor = 
     CompletableFuture.delayedExecutor(1, TimeUnit.MILLISECONDS, executor);

Он возвращает нас к вашему предыдущему вопросу, где я указал , что Executor можно определить с помощью ThreadFactory.

Executor executor = Executors.newCachedThreadPool(YourThreadClass::new);
0 голосов
/ 07 февраля 2019

Исполнитель Новый поток создается для каждого набора задач

Исполнитель обычно используется вместо явного создания потоков.Например, вместо вызова нового потока (new (RunnableTask ())). Start () для каждого из набора задач вы можете использовать: для каждого из набора задач

Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());

Так что, если вы хотите повторно использовать потоки, создайте пул потоков с помощью ExecutorService или ThreadPoolExecutor, чтобы один из потоков из пула выполнял выполняемые задачи.

Если все потоки занятызадачи будут поставлены в очередь до определенного предела и после этого будут отклонены через RejectedExecutionException.

Пример

public class NewMain { 

    private static final ExecutorService ex = Executors.newFixedThreadPool(3);

    public static void main(String[] args) {
        Runnable r = () -> System.out.println(Thread.currentThread().getName());
        ex.execute(r);

        CompletableFuture<Void> c = CompletableFuture.runAsync(r, ex);
    }
}

Jdk-8 Используйте CompletableFuture.runAsync и передайте runnable, Executor

public static CompletableFuture runAsync (поставщик поставщика, Executor executor)

Возвращает новое CompletableFuture, котороеасинхронно завершается задачей, выполняемой в данном исполнителе после выполнения заданного действия.

...