Как запустить JDK 19 со структурированным параллелизмом?

Я отредактировал это, чтобы привести вещи в соответствие с исходной публикацией.

Я хочу попробовать новую функцию Project Loom , определенную в: JEP 428: Structured Concurrency (Incubator)

У меня есть в моем pom.xml

      <properties>
  <maven.compiler.executable>${env.JAVA_HOME}/bin/javac</maven.compiler.executable>
  <maven.compiler.source>19</maven.compiler.source>
  <maven.compiler.target>19</maven.compiler.target>
</properties>

. . .

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.10.1</version>
  <configuration>
    <compilerArgs>
      <arg>--add-modules=jdk.incubator.concurrent</arg>
      <arg>--enable-preview</arg>
    </compilerArgs>
  </configuration>
</plugin>

гдеJAVA_HOMEуказывает на JDK 19, но когда я пытаюсь собрать через него, я получаю

      [ERROR] C:\Users\ERIC\Documents\git\loom-lab\laboratory\src\main\java\net\kolotyluk\loom\Structured.java:3:20:  error: package jdk.incubator.concurrent is not visible
[ERROR] C:\Users\ERIC\Documents\git\loom-lab\laboratory\src\main\java\net\kolotyluk\loom\Structures.java:3:20:  error: package jdk.incubator.concurrent is not visible
. . .

Многие люди помогли мне с этим, и, очевидно, они могут заставить это работать, но по какой-то причине я не могу получитьmvn compileработать.

Однако я могу получить код для компиляции и запуска под IntelliJ. Никогда раньше мне не удавалось заставить Maven скомпилировать, когда я могу заставить IntelliJ сделать это. Обычно бывает наоборот.

2 ответа

файл

Я не понимаю всех движущихся частей, но мне каким-то образом удалось получить доступ к новым функциям Project Loom, виртуальным потокам и , которые были предварительно просмотрены и соответственно в Java 19.

Вот мойmainметод.

      record Event( UUID id , Instant when , Integer reading ) {}

try ( var scope = new StructuredTaskScope.ShutdownOnFailure() )
{
    Future < UUID > futureId = scope.fork( ( ) -> UUID.randomUUID() );
    Future < Instant > futureWhen = scope.fork( ( ) -> Instant.now() );
    Future < Integer > futureReading = scope.fork( ( ) -> ThreadLocalRandom.current().nextInt( 1 , 10 ) );

    scope.join();           // Join both forks
    scope.throwIfFailed();  // ... and propagate errors
    Event event = new Event( futureId.get() , futureWhen.get() , futureReading.get() );
    System.out.println( event );
}
catch ( InterruptedException e )
{
    throw new RuntimeException( e );
}
catch ( ExecutionException e )
{
    throw new RuntimeException( e );
}

Этот код использует этот импорт:

      import java.time.Instant;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadLocalRandom;

При запуске:

Событие[id=de316aca-10b1-41ed-bfc6-732c4e184566, when=2022-08-07T03:04:48.207650Z, чтение=9]

Я добавил файл вне иерархии пакетов, вsrc/main/java.

      module LoomEx {
    requires jdk.incubator.concurrent;
}

И мойPOM. Я начал с архетипа Apache Maven QuickStart из списка . Затем я обновил все номера версий до последних.

      <?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>work.basil.example</groupId>
    <artifactId>Loom</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>Loom</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.release>19</maven.compiler.release>
    </properties>

    <dependencies>

        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.9.0</version>
            <scope>test</scope>
        </dependency>


    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (maybe moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.2.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.3.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.10.1</version>
                    <configuration>
                        <!--<compilerVersion>19</compilerVersion>-->
                        <release>19</release>
                        <!--<compilerArgs>&#45;&#45;source 19</compilerArgs>-->
                        <compilerArgs>--enable-preview</compilerArgs>
                        <!--<compilerArgs>&#45;&#45;add-modules jdk.incubator.concurrent</compilerArgs>-->
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.0.0-M7</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>3.0.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>4.0.0-M3</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.4.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

Я пытался использовать различные элементы Maven POM, взятые из таких страниц, как this , this и this , а также подсказки из инкубированыJEP 11: Incubator Modules и структурированному параллелизмуJEP 428: Structured Concurrency (Incubator) , надеясь, что мне не понадобитсяmodule-info.javaфайл. Но я не мог заставить его работать. Добавление файла информации о модуле было для меня единственным путем к успеху.

И, конечно же, мне пришлось установить обычные несколько странных настроек, которые IntelliJ прячет глубоко в разных разрозненных местах, чтобы указать использование Java 19. См. другие вопросы о переполнении стека для получения указаний по этим неприятным настройкам. (Сводит меня с ума. Определенно самая раздражающая проблема/недостаток в IntelliJ. Почему IntelliJ не может просто прочитать версию Java из настроек Maven POM или Gradle и покончить с этим?)

Небольшое дополнение для отличного ответа @BasilBourque. Для тех людей, которые могут не использовать Maven или модули, вам не нужно будет делать ваше приложение модулем. Параметры для--enable-preview --add-modules jdk.incubator.concurrentтребуются во всех пусковых установках, будь то напрямую или через Maven.

Вы должны иметь возможность запустить пример параллелизма, который он предоставил, из командной строки со стандартным путем к классам и без module-info.java со следующим средством запуска исходного кода или javac/java:

      %JAVAHOME%/bin/java --source 19 --enable-preview --add-modules jdk.incubator.concurrent ConcurrencyEx.java

Или скомпилируйте, а затем запустите его как:

      %JAVAHOME%/bin/javac --source 19 --enable-preview --add-modules jdk.incubator.concurrent -d ../build ConcurrencyEx.java

%JAVAHOME%/bin/java --enable-preview --add-modules jdk.incubator.concurrent -cp ../build ConcurrencyEx

Очевидно, просто заменить%JAVAHOME%с$JAVAHOMEдля запуска в Linux вместо Windows.

Исходный код:

      import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadLocalRandom;
import jdk.incubator.concurrent.*;

public class ConcurrencyEx {
    
    // main as from @BasilBourque answer
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        record Event( UUID id , Instant when , Integer reading ) {}

        try ( var scope = new StructuredTaskScope.ShutdownOnFailure() ) {
            Future < UUID > futureId = scope.fork( ( ) -> UUID.randomUUID() );
            Future < Instant > futureWhen = scope.fork( ( ) -> Instant.now() );
            Future < Integer > futureReading = scope.fork( ( ) -> ThreadLocalRandom.current().nextInt( 1 , 10 ) );

            scope.join();           // Join both forks
            scope.throwIfFailed();  // ... and propagate errors
            Event event = new Event( futureId.get() , futureWhen.get() , futureReading.get() );
            System.out.println( event );
        }
    }
}
Другие вопросы по тегам