Java 8 基本任务的并发最简单规范形式
Java 8 Concurrency Simplest Canonical Form for Basic Task
我有两个问题:
1. 运行 a Callable
作为 Java 8 中任务的最简单规范形式是什么,捕获并处理结果?
2. 在下面的示例中,best/simplest/clearest 保持主进程打开直到所有任务完成的方法是什么?
这是我目前的示例 -- 这是 Java8 中的最佳方法还是有更基本的方法?
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
public class SimpleTask implements Supplier<String> {
private SplittableRandom rand = new SplittableRandom();
final int id;
SimpleTask(int id) { this.id = id; }
@Override
public String get() {
try {
TimeUnit.MILLISECONDS.sleep(rand.nextInt(50, 300));
} catch(InterruptedException e) {
System.err.println("Interrupted");
}
return "Completed " + id + " on " +
Thread.currentThread().getName();
}
public static void main(String[] args) throws Exception {
for(int i = 0; i < 10; i++)
CompletableFuture.supplyAsync(new SimpleTask(i))
.thenAccept(System.out::println);
System.in.read(); // Or else program ends too soon
}
}
有没有更简单明了的Java-8方法呢?我如何消除 System.in.read()
以支持更好的方法?
考虑将未来收集到一个列表中。然后你可以在每个 future 上使用 join()
来等待它们在当前线程中完成:
List<CompletableFuture<Void>> futures = IntStream.range(0,10)
.mapToObj(id -> supplyAsync(new SimpleTask(id)).thenAccept(System.out::println))
.collect(toList());
futures.forEach(CompletableFuture::join);
等待多个 CompletableFuture
实例完成的规范方法是通过 CompletableFuture.allOf
创建一个依赖于所有实例的新实例。您可以使用这个新的未来等待它完成或安排新的后续行动,就像任何其他 CompletableFuture
:
CompletableFuture.allOf(
IntStream.range(0,10).mapToObj(SimpleTask::new)
.map(s -> CompletableFuture.supplyAsync(s).thenAccept(System.out::println))
.toArray(CompletableFuture<?>[]::new)
).join();
当然,如果您放弃为每个任务分配一个唯一的 ID,它总是会变得更简单。由于您的第一个问题是关于 Callable
,我将演示如何通过 ExecutorService
:
轻松提交多个与 Callable
类似的任务
ExecutorService pool = Executors.newCachedThreadPool();
pool.invokeAll(Collections.nCopies(10, () -> {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(
ThreadLocalRandom.current().nextInt(50, 300)));
final String s = "Completed on "+Thread.currentThread().getName();
System.out.println(s);
return s;
}));
pool.shutdown();
Executors.newCachedThreadPool()
返回的执行器服务是非共享的,即使您忘记调用 shutDown()
也不会保持活动状态,但它可能需要一分钟的时间才能终止所有线程.
因为您的第一个问题字面意思是:“运行 中可调用任务的最简单规范形式是什么 Java 8,捕获并处理结果?”,答案可能是最简单的形式仍然是直接调用它的call()
方法,例如
Callable<String> c = () -> {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(
ThreadLocalRandom.current().nextInt(50, 300)));
return "Completed on "+Thread.currentThread().getName();
};
String result = c.call();
System.out.println(result);
没有比这更简单的方法了……
我有两个问题:
1. 运行 a Callable
作为 Java 8 中任务的最简单规范形式是什么,捕获并处理结果?
2. 在下面的示例中,best/simplest/clearest 保持主进程打开直到所有任务完成的方法是什么?
这是我目前的示例 -- 这是 Java8 中的最佳方法还是有更基本的方法?
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
public class SimpleTask implements Supplier<String> {
private SplittableRandom rand = new SplittableRandom();
final int id;
SimpleTask(int id) { this.id = id; }
@Override
public String get() {
try {
TimeUnit.MILLISECONDS.sleep(rand.nextInt(50, 300));
} catch(InterruptedException e) {
System.err.println("Interrupted");
}
return "Completed " + id + " on " +
Thread.currentThread().getName();
}
public static void main(String[] args) throws Exception {
for(int i = 0; i < 10; i++)
CompletableFuture.supplyAsync(new SimpleTask(i))
.thenAccept(System.out::println);
System.in.read(); // Or else program ends too soon
}
}
有没有更简单明了的Java-8方法呢?我如何消除 System.in.read()
以支持更好的方法?
考虑将未来收集到一个列表中。然后你可以在每个 future 上使用 join()
来等待它们在当前线程中完成:
List<CompletableFuture<Void>> futures = IntStream.range(0,10)
.mapToObj(id -> supplyAsync(new SimpleTask(id)).thenAccept(System.out::println))
.collect(toList());
futures.forEach(CompletableFuture::join);
等待多个 CompletableFuture
实例完成的规范方法是通过 CompletableFuture.allOf
创建一个依赖于所有实例的新实例。您可以使用这个新的未来等待它完成或安排新的后续行动,就像任何其他 CompletableFuture
:
CompletableFuture.allOf(
IntStream.range(0,10).mapToObj(SimpleTask::new)
.map(s -> CompletableFuture.supplyAsync(s).thenAccept(System.out::println))
.toArray(CompletableFuture<?>[]::new)
).join();
当然,如果您放弃为每个任务分配一个唯一的 ID,它总是会变得更简单。由于您的第一个问题是关于 Callable
,我将演示如何通过 ExecutorService
:
Callable
类似的任务
ExecutorService pool = Executors.newCachedThreadPool();
pool.invokeAll(Collections.nCopies(10, () -> {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(
ThreadLocalRandom.current().nextInt(50, 300)));
final String s = "Completed on "+Thread.currentThread().getName();
System.out.println(s);
return s;
}));
pool.shutdown();
Executors.newCachedThreadPool()
返回的执行器服务是非共享的,即使您忘记调用 shutDown()
也不会保持活动状态,但它可能需要一分钟的时间才能终止所有线程.
因为您的第一个问题字面意思是:“运行 中可调用任务的最简单规范形式是什么 Java 8,捕获并处理结果?”,答案可能是最简单的形式仍然是直接调用它的call()
方法,例如
Callable<String> c = () -> {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(
ThreadLocalRandom.current().nextInt(50, 300)));
return "Completed on "+Thread.currentThread().getName();
};
String result = c.call();
System.out.println(result);
没有比这更简单的方法了……