Можно ли запустить завершаемое будущее в том же потоке, в котором оно создано? - PullRequest
1 голос
/ 18 марта 2020

Хотелось бы знать, можно ли выполнить завершаемое будущее в потоке, в котором оно было создано. Вы можете спросить, зачем мне это делать, так как completetablefuture предназначен для асинхронного программирования c. Причина в том, что у меня есть несколько асин c задач и некоторые задачи, которые я хочу запустить в порождающем потоке, чтобы я мог использовать allOf et c и поддерживать согласованность в коде

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Когда вы говорите, что хотите знать, можно ли «выполнить завершаемое будущее в потоке, в котором оно было создано», вы демонстрируете неправильное мышление. A CompletableFuture не работает. CompletableFuture просто инкапсулирует значение или исключение, которое может быть установлено не более одного раза, которое мы называем завершением it.

API предлагает множество методов для планирования попыток завершения, потенциально асинхронный, но не стоит отвлекаться от того, что вы решаете, как его завершить.

Существуют простые альтернативы асинхронному завершению:

CompletableFuture<String> f = CompletableFuture.completedFuture("hello");

создает немедленно завершенное будущее. Java 9 добавляет failedFuture для поддержки создания сразу же исключительно завершенного будущего.

Вы также можете легко создать будущее, которое будет завершено позднее в том же потоке:

CompletableFuture<String> f = new CompletableFuture<>();

// arbitrary actions

f.complete("hello");

Вы также можно использовать фабричные методы с исполнителем, немедленно запустив действие в инициирующем потоке:

CompletableFuture<String> f
  = CompletableFuture.supplyAsync(() -> "hello", Runnable::run);

или

CompletableFuture<String> f
  = CompletableFuture.supplyAsync(() -> {
    if(Math.random() > 0.5) throw new IllegalStateException();
    return "hello";
  }, Runnable::run);

, чтобы продемонстрировать разницу с вызовом complete или создание немедленно завершенного будущего.

Конечно, эти возможности могут быть объединены с другими функциями, такими как allOf:

CompletableFuture<String> a = new CompletableFuture<>();
CompletableFuture<String> b = new CompletableFuture<>();
CompletableFuture<String> c = new CompletableFuture<>();

CompletableFuture.allOf(a, b, c).whenComplete((__, t) -> {
  if(t != null) System.err.println("failed with "+t);
  else System.out.println("all completed "+a.join()+", "+b.join()+", "+c.join());
});

System.out.println("step 1");
a.complete("foo");
System.out.println("step 2");
b.complete("bar");
System.out.println("step 3");
c.complete("baz");
1 голос
/ 18 марта 2020

Да, вполне возможно. Вот пример программы, которая демонстрирует

private static Executor executor = Executors.newSingleThreadExecutor();

public static void main(String[] args)
{
    executor.execute(() -> {
        System.out.println("Scheduling " + Thread.currentThread().getName());
        CompletableFuture.supplyAsync(() -> {
            System.out.println("Sleeping " + Thread.currentThread().getName());
            try {
                Thread.sleep(2000);
            }
            catch (InterruptedException e) {}

            System.out.println("Returning " + Thread.currentThread().getName());
            return 123;
        },
        executor)
        .thenAccept(retValue -> System.out.println("Got value " + retValue + " " + Thread.currentThread().getName()));
    });
}

Вывод

Scheduling pool-1-thread-1
Sleeping pool-1-thread-1
Returning pool-1-thread-1
Got value 123 pool-1-thread-1
...