并行执行竞争计算并丢弃除完成的第一个之外的所有计算

fre*_*low 6 java concurrency multithreading scala java.util.concurrent

我写了一个基于随机性生成迷宫的函数.大多数时候,这个功能非常快.但每隔一段时间,由于随机数运气不好,需要几秒钟.

我想多次并行启动这个功能,让最快的功能"赢".

Scala标准库(或Java标准库)是否为此作业提供了合适的工具?

rig*_*old 5

你可以使用Future:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

val futures = for (_ <- 1 to 4) yield Future { /* computation */ }
val resultFuture = Future.firstCompletedOf(futures)
Run Code Online (Sandbox Code Playgroud)

如果你想阻止(我认为你这样做),你可以使用Await.result:

import scala.concurrent.Await
import scala.concurrent.duration.Duration

val result = Await.result(resultFuture, Duration.Inf)
Run Code Online (Sandbox Code Playgroud)


fre*_*low 0

7年后,我偶然发现了它ExecutorService.invokeAny,它正是我想要的:

执行给定的任务,返回已成功完成的任务的结果(即,不引发异常)(如果有的话)(在给定的超时时间过去之前)。

正常或异常返回时,未完成的任务将被取消。

<T> T invokeAny(Collection<? extends Callable<T>> tasks)
    throws InterruptedException, ExecutionException;

<T> T invokeAny(Collection<? extends Callable<T>> tasks,
                long timeout, TimeUnit unit)
    throws InterruptedException, ExecutionException, TimeoutException;
Run Code Online (Sandbox Code Playgroud)

实现草图:

class LabyrinthGenerator implements Callable<Labyrinth> {
    private static final int N = 16;
    private static final ExecutorService pool = Executors.newFixedThreadPool(N);

    public static Labyrinth generate() {
        while (true) {
            List<LabyrinthGenerator> generators = Stream.generate(LabyrinthGenerator::new)
                                                        .limit(N)
                                                        .collect(Collectors.toList());
            try {
                return pool.invokeAny(generators, 1, TimeUnit.SECONDS);
            } catch (InterruptedException | ExecutionException | TimeoutException ex) {
                // all attempts failed or timed out, try again
            }
        }
    }

    @Override
    public Labyrinth call() throws Exception {
        // ...
        if (Thread.currentThread().isInterrupted()) {
            // some other generator found a result, abort
        }
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)