Java 8 Completable Future - 并行执行

标签 java multithreading java-8 completable-future

我正在测试 CompletableFuture 的工作原理。我对如何并行执行任务很感兴趣:

try {
          CompletableFuture one = CompletableFuture.runAsync(() -> {
          throw new RuntimeException("error");
          });
          CompletableFuture two = CompletableFuture.runAsync(() -> System.out.println("2"));
          CompletableFuture three = CompletableFuture.runAsync(() -> System.out.println("3"));
          CompletableFuture all = CompletableFuture.allOf(one, two, three);
          all.get();
} catch (InterruptedException e) {
           System.out.println(e);
} catch (ExecutionException e) {
           System.out.println(e);
}

在这种情况下,它们将被全部执行。

1。当其中一个线程出现异常时,是否可以中断所有正在运行的线程?

2。当此代码位于可从不同线程调用的类方法中时,它是线程安全的吗?

最佳答案

1.Is it possible to interrupt all running threads when there is an exception in one of them?

是的,这是可能的。所有线程都应该可以访问公共(public)对象,该对象的状态可以被其他线程更改和读取。例如,它可以是 AtomicInteger。请参见以下示例:

import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;

public class Dates {

    public static void main(String[] args) throws Exception {
        try {
            AtomicInteger excCounter = new AtomicInteger(0);
            CompletableFuture one = CompletableFuture.runAsync(new ExcRunnable(excCounter));
            CompletableFuture two = CompletableFuture.runAsync(new PrintRunnable("2", excCounter));
            CompletableFuture three = CompletableFuture.runAsync(new PrintRunnable("3", excCounter));
            CompletableFuture all = CompletableFuture.allOf(one, two, three);
            all.get();
        } catch (InterruptedException | ExecutionException e) {
            System.out.println(e);
        }
    }
}

class ExcRunnable implements Runnable {
    private final AtomicInteger excCounter;

    public ExcRunnable(AtomicInteger excCounter) {
        this.excCounter = excCounter;
    }

    @Override
    public void run() {
        Random random = new Random();
        int millis = (int) (random.nextDouble() * 5000);
        System.out.println("Wait " + millis);
        Threads.sleep(450);

        // Inform another threads that exc occurred
        excCounter.incrementAndGet();

        throw new RuntimeException("error");
    }
}

class PrintRunnable implements Runnable {

    private final String name;
    private final AtomicInteger excCounter;

    public PrintRunnable(String name, AtomicInteger excCounter) {
        this.name = name;
        this.excCounter = excCounter;
    }

    @Override
    public void run() {
        int counter = 10;
        while (counter-- > 0 && excCounter.get() == 0) {
            System.out.println(name);
            Threads.sleep(450);
        }
    }
}

class Threads {
    static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

我们有 3 个任务:两个打印它的名字,一个在一段时间后抛出异常。在抛出异常之前,计数器会增加以通知其他任务其中一个任务失败并且它们应该完成执行。打印作业正在检查此计数器,如果不满足条件,它们将完成作业。当您评论 excCounter.incrementAndGet(); 行时,其他任务在不知道其中一个抛出异常的情况下完成了他们的工作。

  1. When this code is inside a class' method which can be invoked from different threads will it be thread safe?

看看 thread safety 的定义.例如,假设打印任务随着打印的每一行递增公共(public)计数器。如果计数器是原始的 int 它不是线程安全的,因为计数器值可以被替换。但是如果你使用 AtomicInteger 它是线程安全的,因为 AtomicInteger 是线程安全的。

关于Java 8 Completable Future - 并行执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55309687/

相关文章:

windows-7 - c :\Windows\System32\java. exe 默认证书存储位置?

c# - 在 .Net 中实现并行任务队列

java - 有没有办法从 java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock 获取 java.util.concurrent.locks.ReentrantReadWriteLock 对象

java - 我怎样才能找到Java中数组的最小覆盖前缀?

java - 线程死锁和同步

java - 带符号的拉丁正则表达式

java - 如何暂停线程一段时间,然后在用户交互后显示UI,继续线程执行

java - 在 Java 中,新建或增强类加载器的用例是什么?

java - 如何使用函数式接口(interface)组织 java 8 代码

java - 如何传递和使用任意 lambda 函数作为参数