Loom Project 是 OpenJDK 在2018年创建的协程方案,是在JVM层实现的有栈协程。到2020年9月为止,该项目还没有明确发布日期,目前可以下载 Early-Access 版本进行试用。
和传统的Java线程相比,loom协程占用内存、CPU资源更少,支持百万数量级的并发。
main.java
import java.time.Instant;
import java.util.List;
import java.util.concurrent.*;
public class main {
public static void main(String[] args) throws Exception {
// ------------------------ Thread API -------------------------------------------------------
// The following uses a static factory method to start a virtual thread.
// It invokes the join method to wait for the thread to terminate.
Thread thread = Thread.startVirtualThread(() -> System.out.println("startVirtualThread"));
thread.join();
// The Thread.Builder API can also be used to create virtual threads that are configured at build time.
// The first snippet below creates an un-started thread.
// The second snippet creates and starts a thread with name "Thread-builder".
Thread thread1 = Thread.builder().virtual().task(() -> System.out.println("Thread.builder build")).build();
thread1.start();
thread1.join();
Thread thread2 = Thread.builder()
.virtual()
.name("Thread-builder")
.task(() -> System.out.println("Thread.builder start, thread name: " + Thread.currentThread().getName()))
.start();
thread2.join();
// The Thread.Builder API can also be used to create a ThreadFactory.
// The ThreadFactory created by the following snippet will create virtual threads
// named "worker-0", "worker-1", "worker-2", ...
ThreadFactory factory = Thread.builder().virtual().name("worker-", 0).factory();
Thread thread3 = factory.newThread(() ->
System.out.println("ThreadFactory thread: " + Thread.currentThread().getName()));
thread3.start();
thread3.join();
thread3 = factory.newThread(() ->
System.out.println("ThreadFactory thread: " + Thread.currentThread().getName()));
thread3.start();
thread3.join();
thread3 = factory.newThread(() ->
System.out.println("ThreadFactory thread: " + Thread.currentThread().getName()));
thread3.start();
thread3.join();
// ------------------------ ExecutorService API ---------------------------------------------------
// The following creates an ExecutorService that runs each task in its own virtual thread.
// The example uses the try-with-resources construct to ensure that the ExecutorService is shutdown
// and that the two tasks (each run in its own virtual thread) complete before continuing.
try (ExecutorService executor = Executors.newVirtualThreadExecutor()) {
executor.execute(() -> System.out.println("newVirtualThreadExecutor 1"));
executor.execute(() -> System.out.println("newVirtualThreadExecutor 2"));
}
// The example below runs three tasks and selects the result of the first task to complete.
// The remaining tasks are cancelled, which causes the virtual threads running them to be interrupted.
try (ExecutorService executor = Executors.newVirtualThreadExecutor()) {
Callable<String> task1 = () -> "foo";
Callable<String> task2 = () -> "bar";
Callable<String> task3 = () -> "baz";
String result = executor.invokeAny(List.of(task1, task2, task3));
System.out.println("invokeAny result: " + result);
}
// This following example uses submitTasks to submit three value returning tasks.
// It uses the CompletableFuture.completed method to obtain a stream that is lazily populated as the tasks complete.
try (ExecutorService executor = Executors.newVirtualThreadExecutor()) {
Callable<String> task1 = () -> "completed foo";
Callable<String> task2 = () -> "completed bar";
Callable<String> task3 = () -> "completed baz";
List<CompletableFuture<String>> cfs = executor.submitTasks(List.of(task1, task2, task3));
CompletableFuture.completed(cfs)
.map(CompletableFuture::join)
.forEach(System.out::println);
}
// The following creates an ExecutorService that runs each task in its own virtual thread with a deadline.
// If the deadline expires before the executor has terminated then the thread executing this code
// will be interrupted and any tasks running will be cancelled. (which causes the virtual thread to be interrupted).
Instant deadline = Instant.now().plusSeconds(1);
try (ExecutorService executor = Executors.newVirtualThreadExecutor().withDeadline(deadline)) {
executor.submit(() -> {
try {
Thread.sleep(500);
System.out.println("withDeadline 500");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
executor.submit(() -> {
try {
Thread.sleep(800);
System.out.println("withDeadline 800");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
executor.submit(() -> {
try {
Thread.sleep(1200);
System.out.println("withDeadline 1200");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
}
}
输出:
startVirtualThread
Thread.builder build
Thread.builder start, thread name: Thread-builder
ThreadFactory thread: worker-0
ThreadFactory thread: worker-1
ThreadFactory thread: worker-2
newVirtualThreadExecutor 1
newVirtualThreadExecutor 2
invokeAny result: foo
completed foo
completed bar
completed baz
withDeadline 500
withDeadline 800
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.target>16</maven.compiler.target>
<maven.compiler.source>16</maven.compiler.source>
</properties>
</project>