Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用ExecutorService时出现超时问题_Java_Multithreading_Concurrency_Executorservice - Fatal编程技术网

Java 使用ExecutorService时出现超时问题

Java 使用ExecutorService时出现超时问题,java,multithreading,concurrency,executorservice,Java,Multithreading,Concurrency,Executorservice,我有一个数十万可调用对象的列表。当每一个都运行时,它会根据给定的值执行可能很长的计算。因此,我希望异步运行每个任务(最好通过使用某种执行器),并在30秒后检索每个计算的结果,取消那些没有及时完成的计算。(获得的值用于其他地方。) 到目前为止,我是这样实现的: private void process() { class Runner implements Callable<BigDecimal> { final int x, y; Runne

我有一个数十万可调用对象的列表。当每一个都运行时,它会根据给定的值执行可能很长的计算。因此,我希望异步运行每个任务(最好通过使用某种执行器),并在30秒后检索每个计算的结果,取消那些没有及时完成的计算。(获得的值用于其他地方。)

到目前为止,我是这样实现的:

private void process() {
    class Runner implements Callable<BigDecimal> {
        final int x, y;

        Runner(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public BigDecimal call() {
            BigDecimal gWidth = xMax.subtract(xMin), gHeight = yMax.subtract(yMin);
            BigDecimal gy = gHeight.multiply(BigDecimal.valueOf(-y)).divide(BigDecimal.valueOf(height)).add(yMax);
            BigDecimal gx = gWidth.multiply(BigDecimal.valueOf(x)).divide(BigDecimal.valueOf(width)).add(xMin);

            // The calculation begins when this method is called
            BigDecimal result = calculateAt(gx, gy);
            return result;
        }
    }

    ExecutorService exec = Executors.newCachedThreadPool();
    List<Runner> runners = new ArrayList<>();
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            runners.add(new Runner(x, y));
        }
    }

    try {
        List<Future<BigDecimal>> results = exec.invokeAll(runners, 30, TimeUnit.SECONDS);
        for (Future<BigDecimal> future : results) {
            // Check if the future's task was cancelled and process the results
        }
    } catch (InterruptedException | ExecutionException ex) {
        ex.printStackTrace();
    }
    exec.shutdown();
}

// Extra variables and methods
BigDecimal xMin = BigDecimal.valueOf(-7),
           xMax = BigDecimal.valueOf(7),
           yMin = BigDecimal.valueOf(-7),
           yMax = BigDecimal.valueOf(7);
int height = 850, width = 850;
private BigDecimal calculateAt(BigDecimal x, BigDecimal y) {
    try {
        // Just to simulate a potential execution time
        Thread.sleep((ThreadLocalRandom.current().nextInt(45) + 1) * 1000);
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
    return BigDecimal.ONE;
}
private void进程(){
类运行程序实现了可调用的{
最终整数x,y;
流道(内部x,内部y){
这个.x=x;
这个。y=y;
}
@凌驾
公共BigDecimal调用(){
BigDecimal gWidth=xMax.subtract(xMin),gHeight=yMax.subtract(yMin);
BigDecimal gy=gHeight.multiply(BigDecimal.valueOf(-y)).divide(BigDecimal.valueOf(height)).add(yMax);
BigDecimal gx=gWidth.multiply(BigDecimal.valueOf(x)).divide(BigDecimal.valueOf(width)).add(xMin);
//当调用此方法时,计算开始
BigDecimal结果=计算(gx,gy);
返回结果;
}
}
ExecutorService exec=Executors.newCachedThreadPool();
List runner=new ArrayList();
对于(int y=0;y
ArrayList
runners
存储每个要执行的
Callable
,然后将其发送到ExecutorService以运行所有任务。我遇到的问题是,任务似乎是同步启动的,在超时30秒后,只有前4万或5万个任务完成了,更不用说开始执行了


似乎正在发生的是,
ExecutorService.invokeAll
方法只允许列表中的所有任务在30秒的时间内开始和完成执行。相反,我需要的是在每个任务的基础上开始这个30秒的窗口,也就是说,一旦任务已经开始,就给它30秒的时间让它完成
invokeAll
似乎不能做到这一点,至少在
newCachedThreadPool
中不能做到这一点。是否有Java库或其他实现方法可以这样做?

最简单的方法是单独调用每个任务,例如在初始化
运行程序的循环中。由于您上面提到的行为符合,所以没有子类(至少是Java标准版附带的子类)的行为会有所不同。实现这种行为的独特函数也不存在


#invokeAll(List的文档中,我认为您可以用解决这个问题

例如,以下是基于问题片段的代码:

private static final ExecutorService executor = Executors.newCachedThreadPool();
private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(100);

private static void processAsync() {
  List<CompletableFuture<Object>> futureList = IntStream.range(0, height).boxed()
    .flatMap(y -> IntStream.range(0, width).boxed().map(x -> new Runner(x, y)))
    .map(runner ->
      CompletableFuture.anyOf(
        CompletableFuture.supplyAsync(runner, executor),
        timeout(Duration.ofSeconds(30))
      ).exceptionally(throwable -> {
        // timeout is handled here
        return BigDecimal.ZERO;
      })
    )
    .collect(Collectors.toList());

  CompletableFuture.allOf(futureList.toArray(new CompletableFuture<?>[0]))
    .thenAccept(v -> {
      List<BigDecimal> results = futureList.stream()
        .map(CompletableFuture::join)
        .map(r -> (BigDecimal) r)
        .collect(Collectors.toList());
      // process final results
      BigDecimal sum = results.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
      System.out.println("Final sum: " + sum);
    })
    .exceptionally(throwable -> {
      System.out.println("Failed allOf with " + throwable);
      return null;
    });
}

private static CompletableFuture<BigDecimal> timeout(Duration duration) {
  CompletableFuture<BigDecimal> future = new CompletableFuture<>();
  scheduler.schedule(
    () -> future.completeExceptionally(new TimeoutException("Timeout " + Thread.currentThread().getName())), duration.toMillis(), MILLISECONDS);
  return future;
}

private static class Runner implements Supplier<BigDecimal> {...
private static final executor service executor=Executors.newCachedThreadPool();
private static final ScheduledExecutorService scheduler=Executors.newScheduledThreadPool(100);
私有静态void processAsync(){
List futureList=IntStream.range(0,高度).boxed()
.flatMap(y->IntStream.range(0,宽度).boxed().map(x->newrunner(x,y)))
.map(跑步者->
完全的未来(
CompletableFuture.SupplySync(运行者、执行者),
超时(持续时间秒(30))
).例外情况下(可丢弃->{
//超时在这里处理
返回BigDecimal.ZERO;
})
)
.collect(Collectors.toList());
CompletableFuture.allOf(futureList.toArray(新的CompletableFuture[0]))
.然后接受(v->{
列表结果=futureList.stream()
.map(CompletableFuture::join)
.map(r->(BigDecimal)r)
.collect(Collectors.toList());
//处理最终结果
BigDecimal sum=results.stream().reduce(BigDecimal.ZERO,BigDecimal::add);
System.out.println(“最终总和:+总和”);
})
.例外情况下(可丢弃->{
System.out.println(“失败的allOf,带“+可丢弃”);
返回null;
});
}
专用静态CompletableFuture超时(持续时间){
CompletableFuture=新的CompletableFuture();
时间表(
()->future.completeException(新的TimeoutException(“Timeout”+Thread.currentThread().getName())、duration.toMillis()、毫秒);
回归未来;
}
私有静态类运行程序实现供应商{。。。

这里的主要思想是使用
CompletableFuture.anyOf
并将其应用于有用任务的
CompletableFuture
和超时任务的
CopmpletableFuture
。超时是通过使用
ScheduledExecutorService
CompletableFuture.completeetException
实现的。因此,基本上,
anyOf
returns result或
TimeoutException
我会尝试一下。小错误:
supplyAsync(runner,executor)
应该是
supplyAsync(()->runner,executor)
。无需在第二个
IntStream
上使用
boxed()
。两个问题:这是否保留了
R的顺序