From 6ebcdca03c5b810da97270305eb2542277b875e4 Mon Sep 17 00:00:00 2001 From: Raul Estrela Date: Sat, 25 Nov 2023 16:40:23 +0100 Subject: [PATCH] virtual threads examples --- .github/workflows/build.yml | 17 +++++++++ .gitignore | 3 ++ .mvn/wrapper/maven-wrapper.properties | 2 + README.md | 7 +++- pom.xml | 26 +++++++++++++ .../estrela/jvt/MultiplePlatformThreads.java | 37 +++++++++++++++++++ .../estrela/jvt/MultipleVirtualThreads.java | 26 +++++++++++++ src/main/java/me/estrela/jvt/ThreadUtils.java | 11 ++++++ .../estrela/jvt/VirtualThreadsExecutors.java | 22 +++++++++++ .../me/estrela/jvt/VirtualThreadsStarter.java | 21 +++++++++++ 10 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build.yml create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 pom.xml create mode 100644 src/main/java/me/estrela/jvt/MultiplePlatformThreads.java create mode 100644 src/main/java/me/estrela/jvt/MultipleVirtualThreads.java create mode 100644 src/main/java/me/estrela/jvt/ThreadUtils.java create mode 100644 src/main/java/me/estrela/jvt/VirtualThreadsExecutors.java create mode 100644 src/main/java/me/estrela/jvt/VirtualThreadsStarter.java diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..941eddd --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,17 @@ +name: build +on: + push: + branches: + - main + workflow_dispatch: +jobs: + job-container: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '21' + - id: compile-sources + run: mvn verify -pl source \ No newline at end of file diff --git a/.gitignore b/.gitignore index 524f096..b98b9fa 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* replay_pid* + +.idea +target \ No newline at end of file diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..9f220ac --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar \ No newline at end of file diff --git a/README.md b/README.md index db652d7..d18cdff 100644 --- a/README.md +++ b/README.md @@ -1 +1,6 @@ -# java-virtual-threads \ No newline at end of file +# Java Virtual Threads + +![build-status](https://github.com/rsaestrela/java-virtual-threads/workflows/build/badge.svg) + +This repository contains a few code samples of the usage of Virtual Threads, a feature described in JEP 444 and released +in Java 21. \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..6ead9e4 --- /dev/null +++ b/pom.xml @@ -0,0 +1,26 @@ + + 4.0.0 + me.estrela + java-virtual-threads + 0.0.1-SNAPSHOT + Java Virtual Threads + estrela.me + + 21 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 21 + 21 + true + + + + + diff --git a/src/main/java/me/estrela/jvt/MultiplePlatformThreads.java b/src/main/java/me/estrela/jvt/MultiplePlatformThreads.java new file mode 100644 index 0000000..c3b37dc --- /dev/null +++ b/src/main/java/me/estrela/jvt/MultiplePlatformThreads.java @@ -0,0 +1,37 @@ +package me.estrela.jvt; + +import java.time.Duration; +import java.util.concurrent.atomic.AtomicLong; + +import static me.estrela.jvt.ThreadUtils.describe; + +public class MultiplePlatformThreads { + + public static void main(String[] args) { + + AtomicLong runningThreadsCounter = new AtomicLong(); + + long startTime = System.currentTimeMillis(); + + for (int i = 1; i <= 5_000; i++) { + Thread vThread = Thread.ofPlatform() + .name("platform-thread") + .start(() -> { + runningThreadsCounter.incrementAndGet(); + try { + Thread.sleep(Duration.ofMinutes(30)); + } catch (InterruptedException e) { + // Let the thread die + } + }); + System.out.println(describe(vThread)); + if (i % 100 == 0) { + long time = System.currentTimeMillis() - startTime; + System.out.printf("%,d threads started, %,d threads running after %,d ms%n", i, runningThreadsCounter.get(), time); + } + } + + } + +} + diff --git a/src/main/java/me/estrela/jvt/MultipleVirtualThreads.java b/src/main/java/me/estrela/jvt/MultipleVirtualThreads.java new file mode 100644 index 0000000..a9fdd5f --- /dev/null +++ b/src/main/java/me/estrela/jvt/MultipleVirtualThreads.java @@ -0,0 +1,26 @@ +package me.estrela.jvt; + +import java.time.Duration; + +import static me.estrela.jvt.ThreadUtils.describe; + +public class MultipleVirtualThreads { + + public static void main(String[] args) { + Runnable runnable = () -> { + try { + Thread.sleep(Duration.ofMinutes(30)); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + }; + for (int i = 0; i < 100_000_000; i++) { + Thread vThread = Thread.ofVirtual() + .name("virtual-thread") + .start(runnable); + System.out.println(describe(vThread)); + } + + } + +} diff --git a/src/main/java/me/estrela/jvt/ThreadUtils.java b/src/main/java/me/estrela/jvt/ThreadUtils.java new file mode 100644 index 0000000..3c2566f --- /dev/null +++ b/src/main/java/me/estrela/jvt/ThreadUtils.java @@ -0,0 +1,11 @@ +package me.estrela.jvt; + +public final class ThreadUtils { + + public static String describe(Thread thread) { + return String.format("Thread %s-%s isVirtual=%s status=%s activeThreads=%s", + thread.getName(), thread.threadId(), thread.isVirtual(), thread.getState().name(), Thread.activeCount()); + } + + +} diff --git a/src/main/java/me/estrela/jvt/VirtualThreadsExecutors.java b/src/main/java/me/estrela/jvt/VirtualThreadsExecutors.java new file mode 100644 index 0000000..087dc94 --- /dev/null +++ b/src/main/java/me/estrela/jvt/VirtualThreadsExecutors.java @@ -0,0 +1,22 @@ +package me.estrela.jvt; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class VirtualThreadsExecutors { + + public static void main(String[] args) { + + try (ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor()) { + Future future = executorService.submit(() -> 1 + 1); + Integer result = future.get(); + System.out.printf("Task completed with result=%s", result); + } catch (InterruptedException | ExecutionException e) { + throw new IllegalStateException(e); + } + + } + +} diff --git a/src/main/java/me/estrela/jvt/VirtualThreadsStarter.java b/src/main/java/me/estrela/jvt/VirtualThreadsStarter.java new file mode 100644 index 0000000..073b0ac --- /dev/null +++ b/src/main/java/me/estrela/jvt/VirtualThreadsStarter.java @@ -0,0 +1,21 @@ +package me.estrela.jvt; + +import static me.estrela.jvt.ThreadUtils.describe; + +public class VirtualThreadsStarter { + + public static void main(String[] args) throws InterruptedException { + + Thread vThread = Thread.ofVirtual() + .name("virtual-thread") + .start(() -> System.out.println("Started Virtual Thread!")); + + System.out.printf(describe(vThread)); + + vThread.join(); + + System.out.printf(describe(vThread)); + + } + +}