Quasar invokeAny
Я написал ExecutorService, который используется для параллельного выполнения нескольких потоков и получения первого найденного результата. Для этого я использую метод invokeAny.
Что-то похожее на следующее:
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>() {
public String call() throws Exception {
System.out.println("Task 1 started...");
return "Task 1 Finished";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
System.out.println("Task2 started...");
return "Task 2 Finished";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 3 Finished";
}
});
try {
String result = executorService.invokeAny(callables);
System.out.println("result = " + result);
} catch (Throwable e) {
e.printStackTrace();
}
executorService.shutdown();
}
}
Все работает нормально, но поскольку мой код выполняет много потоков, используется огромное количество ресурсов (ЦП). Поэтому я заглянул в интернет и обнаружил, что люди предлагают использовать Quasar для решения подобных проблем... Исходя из спецификации, он должен работать как "параллельный" фреймворк java, поэтому я посмотрел и нашел класс "FiberExecutorScheduler", который кажется многообещающим, но я не могу найти способ организовать свою работу, чтобы реализовать то же поведение моего предыдущего кода.
Есть ли способ реализовать это с помощью Quasar? Можете ли вы привести пример? Любая помощь будет оценена.
1 ответ
Согласно документации по волокну, вы можете перевести ваш Callable в Fiber согласно приведенному ниже коду, где V - ваш тип возврата.
new Fiber<V>() {
@Override
protected V run() throws SuspendExecution, InterruptedException {
// your code
}
}.start();
И вы можете перевести ExecutorService
к FiberExecutorScheduler
куда можно позвонить newFiber
добавить ваше волокно к исполнителю.
Мне не хватало документации для этой библиотеки. Нет примеров использования, даже на их собственном сайте. Заглядывая в их репо, я нашел следующий тестовый пример.
@Test
public void simpleTest1() throws Exception {
final CompletableFuture<String> fut = new CompletableFuture<String>();
final Fiber<String> fiber = new Fiber<>(scheduler, () -> {
try {
return AsyncCompletionStage.get(fut);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(200);
fut.complete("hi!");
} catch (InterruptedException e) {
}
}
}).start();
assertThat(fiber.get(), equalTo("hi!"));
}
Я бы попробовал продолжить на основе этого теста на вашем месте.