如何使用java8 Labmdas和线程池实例化Object或调用setter来传递来自不同线程的值?

Igo*_*gor 3 java java-8

我有这样的旧式代码:

ObjectToInstantiate instance = new ObjectToInstantiate();
Thread getFirstValueThread = new Thread(() -> instance.setFirstValue(service.getFirstValue));
Thread getSecondValueThread = new Thread(() -> instance.setSecondValue(service.getSecondValue));

getFirstValueThread.start();
getSecondValueThread.start();

try {
  getFirstValueThread.join();
  getSecondValueThread.join();
} catch (InterruptedException e) {
  throw new RuntimeException(e.getMessage(), e);
}
return instance;
Run Code Online (Sandbox Code Playgroud)

FirstValue和SecondValue是不同的类,我也可以将它们传递给构造函数,而不仅仅是setter.

我怎样才能使用ExecutorService或其他东西来避免新的线程创建?

Ash*_*Ash 6

看看CompletableFutures,它的设计理念是在给定的一段时间后返回值.您也可以轻松管理异常案例.

CompletableFuture<FirstValue> f1 = CompletableFuture.supplyAsync(() -> service.getFirstValue());
CompletableFuture<SecondValue> f2 = CompletableFuture.supplyAsync(() -> service.getSecondValue());

CompletableFuture<ObjectToInstantiate> combineFuture = f1.thenCombine(f2, (firstValue, secondValue) -> new ObjectToInstantiate (firstValue, secondValue));
ObjectToInstantiate myObject = combineFuture .join();
Run Code Online (Sandbox Code Playgroud)

这样做是创建两个返回值的异步线程.f1.thenCombine在成功完成时获取两者的值,并组合两者的值以创建新对象.

您现在不使用方法的副作用,但实际上返回并移动值以创建新对象.

另外,根据您在对象上的构造函数的方式,您可能也可以这样做

f1.thenCombine(f2, ObjectToInstantiate::new);
Run Code Online (Sandbox Code Playgroud)

您也可以为异步方法执行此操作

CompletableFuture.supplyAsync(service::getFirstValue)
Run Code Online (Sandbox Code Playgroud)

此外,如果您已经有执行服务,您可以更改

CompletableFuture.supplyAsync(() -> service.getFirstValue);
Run Code Online (Sandbox Code Playgroud)

CompletableFuture.supplyAsync(() -> service.getFirstValue, myExecutorService);
Run Code Online (Sandbox Code Playgroud)