在ForkJoinpool上使用CompletableFuture并避免线程等待

时间:2016-08-26 15:09:16

标签: java multithreading asynchronous completable-future work-stealing

您好我认为CompletableFuture和默认ForkJoinPool我可以优化任务的执行而不是经典的ExecutorService,但我遗漏了一些东西

使用此代码执行需要1秒,我有3个工作线程:

for (int i = 0; i < 3; i++) {
    final int counter = i;
    listTasks.add(CompletableFuture.supplyAsync(() -> {
        Thread.sleep(1000);
        System.out.println("Looking up " + counter + " on thread " + Thread.currentThread().getName());
        return null;
    }));
}

好的,似乎很正常。

但是使用此代码,需要3秒钟:

for (int i = 0; i < 9; i++) {
    final int counter = i;
    listTasks.add(CompletableFuture.supplyAsync(() -> {
        Thread.sleep(1000);
        System.out.println("Looking up " + counter + " on thread " + Thread.currentThread().getName());
        return null;
    }));
}

我认为睡眠线程将用于启动其他等待任务,它还需要1秒钟。我已经读过,例如IO WAINTING线程状态意味着该线程可以重用于其他任务。我可以使用Thread.sleep()测试此行为吗?我的测试方法是错误的还是我理解错误?

2 个答案:

答案 0 :(得分:2)

休眠线程不能用于执行另一个线程的工作(特别是,一个线程无法为另一个线程休眠)。当第一个线程进入休眠状态时,它只能切换到第二个线程。

当您向..... ..... ..... // Declare click response : playBoard[i][j].setOnAction(e -> { n = Integer.parseInt(((Button)e.getSource()).getText()); toggleColorButtonRed((Button)e.getSource(), n); }); ..... ..... ..... private void toggleColorButtonRed(Button button, int n) { Color color = (Color)button.getBackground().getFills().get(0).getFill(); if (color != Color.RED) button.setBackground(new Background(new BackgroundFill( Color.RED, CornerRadii.EMPTY, Insets.EMPTY))); else { System.out.println("You have clicked a " + color + " square !"); if (n % 2 == 0) button.setBackground(new Background(new BackgroundFill( Color.ORANGE, CornerRadii.EMPTY, Insets.EMPTY))); else button.setBackground(new Background(new BackgroundFill( Color.BLUE, CornerRadii.EMPTY, Insets.EMPTY))); } } OUTPUT WHEN A SQUARE IS CLICKED TWICE ===================================== You have clicked a 0xff0000ff square ! 提供任务时,它将转到默认的CompletableFuture.supplyAsync()实例,该实例的线程数与计算机的CPU数一样多。您手动将分配的三个线程设置为默认的ForkJoinPool,因此您的九个任务在它们之间平均分配:每个线程连续执行三个任务。所以,你有三秒钟的结果。

答案 1 :(得分:1)

我们来算一算。如果你有9个任务,每个任务睡眠1秒,你有2个处理器,你一次只能运行2个1秒的睡眠。使用9个任务运行此任务,您至少经过3秒或最多经过4秒。

这与非阻塞IO不同,因为此Runnable线程受CPU限制,并且在完成之前不会放弃CPU(尽管处于休眠状态)。如果你看一下RxJava的IO线程池之类的东西,它会为每个任务创建一个线程,这对IO任务是可接受的(但不是CPU绑定任务)。