Project Loom: Modern Scalable Multithreading for the Java Platform







β€” , . Java concurrency. concurrency-, , , .







β€” Project Loom. Java .







, OpenJDK Core Libraries Project, Loom , Java . Joker 2020. β€” .









, Java Platform Oracle, OpenJDK. Project Loom.







2017 (, 2018-). OpenJDK , . , . β€” β€” , . , .







- : , .







:







  1. .
  2. , .
  3. IDE , .
  4. , .




Java ( , JVM) :







  • , .
  • , ThreadLocal.
  • , . step over, , .
  • , , , .


, , , .







Java API java.lang.Thread. JDK , . java.lang.Thread --. , Java, JDK. . 20 , java.lang.Thread, .







C Java. . . , , ,

, .







, ​​ ,

. .







, ​​ . ,

. - , , , . , .







. , . , . . . , , . , , .







Java. . , , . , .







, β€” , . , .







. , Project Loom, . , .







, , , , . . , , .







, ?







β€” , ? . , , .







. , , , , ThreadLocals. . : , , , , , .







, , . , - , .







, ,

CPU, , , , IO, - . , , , .







, , . . , API, API, - β€” , .







API, , . API.







, , . β€” , . , , , β€” , .







, . , , . , IO. , , .







, . , . . , .







, , .







.













. , , .







, ? , ? , , . Project Loom .







API



API.







Project Loom , API? , , .







, , β€”

java.lang.Thread. API, JDK 1.0. , «». , , . API, , .







β€”

API. Project Loom, , , API fiber.







API, , . , , β€” . Thread.currentThread() , , .







, : Β« Thread.currentThread() ?Β» , , 2 5. β€” 113.







β€” ThreadLocals. , . Thread.currentThread() ThreadLocals, . , fiber API, Thread API, , fiber. , , Thread, .







, .currentThread() Threadlocals . «». . , , , , β€” , , java.lang.Thread.







, β€” ,

25 . API java.lang.Thread. java.lang.Thread , .







. , Β« Β» (virtual thread).







Thread β€” . , , . «», , , ThreadLocals .







?













. «» , green threads. JDK, 1.0.1.1 , , - . , , , .







, , . HotSpot ​​ : scoped stackful one-shot delimited continuations. HotSpot Java. , , , , IO-, , , , Java, . .







, , , . , . , .







, API Java, ,

, yield resume JDK, , .







, , .













. , 16 . , . , HotSpot .







, 256 . , β€”

.







, , . , . , , ,

.







IDE .









IDE , .







import ...

public class Demo {
    public static void main(String[] args) throws Exception {...}

    void run() throws Exception {

    }
}

      
      





, , Thread.startVirtualThread().







import ...

public class Demo {
    public static void main(String[] args) throws Exception {...}

    void run() throws Exception {

        Thread thread = Thread.startVirtualThread(() -> System.out.println("hello"));
        thread.join();

    }
}

      
      





Β«helloΒ», . start(), .







-, , , .







void run() throws Exception {

    Thread thread = Thread.startVirtualThread(Thread::dumpStack);
    thread.join();

}

      
      





- .













, , , java.lang.Thread



, , , , JDK. , . , .







API. startVirtualThread()



?







, . Thread.builder()



. , : -, .













virtual(). c startVirtualThread()



, , , . , :







void run() throws Exception {

    Thread thread = Thread.builder().virtual().task(() -> {
        System.out.println("hello");
    }).start();

    thread.join();

    }

}

      
      





, . , , setDaemon() setName(). .







API , Thread API . β€” , startVirtualThread().







ThreadFactory.







void run() throws Exception {
    ThreadFactory factory = Thread.builder().name("worker-", 0).factory();
}
      
      





β€” , worker-0, worker-1, worker-2 . worker β€” , . .







, , , .







Thread API . JDK 5, ThreadExecutor API java.util.concurrent.







ThreadExecutor. , .







ExecutorService executor:







try (ExecutorService executor = Executors.newVirtualThreadExecutor()) {

}

      
      





Executors . , try-with-resources. , Loom, β€” ExecutorService AutoCloseable, try-with-resources.







, , , , , , , . , , . Executor' , , Executors.







.







import ...

  public class Demo {
      public static void main(String[] args) throws Exception {...}

      void run() throws Exception {
          try (ExecutorService executor = Executors.newVirtualThreadExecutor()) {
              IntStream.range(0, 1_000_000).forEach(i -> {
                  executor.submit(() -> { });
              });
          }
      }

      String fetch(String url) throws IOException {...}

      void sleep(Duration duration) {...}
  }

      
      





IntStream.range(), for. executor.submit() , , . , β€” Β«Process finished with exit code 0Β».







, .







import ...

public class Demo {
    public static void main(String[] args) throws Exception {...}

    void run() throws Exception {
        AtomicInteger counter = new AtomicInteger();
        try (ExecutorService executor = Executors.newVirtualThreadExecutor()) {
            IntStream.range(0, 1_000_000).forEach(i -> {
                executor.submit(counter::incrementAndGet);
            });
        }
        System.out.println(counter.get());
    }

    String fetch(String url) throws IOException {...}

    void sleep(Duration duration) {...}
  }
      
      





Executor, , , , . , , .







β€” , .







, Executor'. , URL-, . β€” , .







String fetch(String url) throws IOExpection {
    try (InputStream in = URI.create(url).toURL().openStream()) {
        byte[] bytes = in.readAllBytes();
        return new String(bytes, "ISO-8859-1");
    }
}

      
      





, HTTP- , .







:







void run() throws Exception {

       try (ExecutorService executor = Executors.newVirtualThreadExecutor()) {

           Callable<String> task1 = () -> fetch("https://jokerconf.com/");
           Callable<String> task1 = () -> fetch("https://jokerconf.com/en");

           String first = executor.invokeAny(List.of(task1, task2));
           System.out.println(first.length());
       }     
}

      
      





, HTML- jokerconf.com. , , . - , , .







executor.invokeAny()



.

ExecutorService , invokeAny()



, invokeAll()



, . .







first , , .







. , β€” , , , String first. (). β€” : Β«200160Β», 200 .







, : , URL-, β€” URL-, , . , : 178 , β€” 200 .







. , - , invokeAll()



.







void run() throws Exception {

       try (ExecutorService executor = Executors.newVirtualThreadExecutor()) {

           Callable<String> task1 = () -> fetch("https://jokerconf.com/");
           Callable<String> task1 = () -> fetch("https://jokerconf.com/en");

           executor.invokeAll(List.of(task1, task2))
                   .stream() 
                   .map(Future::join) 
                   .map(String::length) 
                   .forEach(System.out.println);
       }     
}

      
      





, β€” , , invokeAll()



. , . InvokeAll()



, , Future, . , , , . 200 178 . ExecutorService.







-. Loom CompletableFuture, . CompletableFuture, Future, :







void run() throws Exception {

       try (ExecutorService executor = Executors.newVirtualThreadExecutor()) {

           Callable<String> task1 = () -> fetch("https://jokerconf.com/");
           Callable<String> task1 = () -> fetch("https://jokerconf.com/en");

           CompletableFuture<String> future1 = executor.submitTask(task1);
           CompletableFuture<String> future2 = executor.submitTask(task2);

           CompletableFuture.completed(future1, future2)
                   .map(Future::join) 
                   .map(String::length) 
                   .forEach(System.out.println);
       }     
}

      
      





CompletableFuture- completed(). , Future . , invokeAll(), , , . . - CompletionService, - .







, , , . , , CompletableFuture, .







, , . . . , , IO-, . , IDE, , .







import ...

public class Demo {
    public static void main(String[] args) throws Exception {...}

    void run() throws Exception {

        Thread.startVirtualThread(() ->

            sleep(Duration.ofSeconds(2));

        }).join();
    }

    String fetch(String url) throws IOException {...}

    void sleep(Duration duration) {...}
  }

      
      





, , . . , , .







void run() throws Exception {

        Thread.startVirtualThread(() -> {

            Object lock = new Object();
            synchronized (lock) {
                sleep(Duration.ofSeconds(2));
            }
        }).join();

}

      
      





, , .













, , . , , . . , , . , , . , c , . .







, .







package demo;

import ...

@Path("/")
public class SleepService {

    @GET
    @Path("sleep")
    @Producers(MediaType.APPLICATION_JSON)
    public String sleep(@QueryParam("millis") long millis) throws Exception {
        Thread.sleep(millis);
        return "{ \"millis\": \"" + millis + "\" };
    }
}

      
      





, .

Helidon MP. , MP MicroProfile. Helidon , , , . , . , , , .







, , β€” - Β«hello worldΒ» . , curl-.













Curl- JSON, .

, , , β€” . Thread.dumpStack():







public String sleep(@QueryParam("millis") long millis) throws Exception {
    Thread.dumpStack();
    Thread.sleep(millis);
    return "{ \"millis\": \"" + millis + "\" };
}

      
      





. curl, HTTP- , , β€” millis=100.







curl http://localhost:8081/sleep?millis=100









: , Thread.dumpStack()



.













, : Helidon, Weld, JAX-RS… . , , .







.

invokeAny involeAll , ExecutorService.







import ...

@Path("/")
public class AggregatorServices {

    @GET
    @Path("anyOf")
    @Produces(MediaType.APPLICATION_JSON)
    public String anyOf(@QueryParam("left") String left,
                        @QueryParam("right") String right) throws Exception {
        if (left == null || right == null) {
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }

        try (var executor = Executors.newVirtualThreadExecutor()) {
            Callable<String> task1 = () -> query(left);
            Callable<String> task2 = () -> query(right);

            // return the first to succeed, cancel the other
            return executor.invokeAny(List.of(task1, task2));
        }
    }

    @GET
    @Path("allOf")
    @Produces(MediaType.APPLICATION_JSON)
    public String allOf(@QueryParam("left") String left,
                        @QueryParam("right") String right) throws Exception {

        if (left == null || right == null) {
            throw new WebApplicationException(Response.Status.BAD_REQUEST)
        }

        try (var executor = Executors.newVirtualThreadExecutor()) {
            Callable<String> task1 = () -> query(left);
            Callable<String> task2 = () -> query(right);

            // if one falls, the other is cancelled
            return executor.invokeAll(List.of(task1, task2), true)
                    .stream() 
                    .map(Future::join) 
                    .collect(Collectors.joining(", ", "{", " }"));
        }
    }

    private String query(String endpoint) {...}
}

      
      





, AggregatorServices. , : anyOf allOf. anyOf , , .







anyOf. curl-:







curl http://localhost:8081/anyOf?left=/greeting\&right=/sleep?millis=200
      
      





localhost:8081 β€” , β€” anyOf, β€” left right. Β«hello worldΒ»:







{"message":"Hello World!"}









, Β«hello worldΒ», 200 . , Β«hello worldΒ» , 200 , Β«hello worldΒ».







1 , , , , .







allOf, :







curl http://localhost:8081/allOf?left=/greeting\&right=/sleep?millis=1
      
      





.







{ {"message":"Hello World!"}, { "millis": "1" } }









allOf, .







private String query(String endpoint) {
        URI uri = URI.create("http://localhost:8081").resolve(endpoint);
        return ClientBuilder.newClient()
                    .target(uri)
                    .request(MediaType.APPLICATION_JSON)
                    .get(String.class);
    }

      
      





, . API JAX-RS . invokeAll(), .stream (), .map , Collectors.joining(), JSON.







. , invokeAll() β€” , cancelOnException. , , . , .







Loom. JDK 16, , β€” JDK 16, , Loom.









.







, , , . , , , .







, . JNI, JNI, Java, Java IO-. , . , .







, , :

, . , , , . , . , .







. , , Java, synchronized wait-notify java.util.concurrent. java.util.concurrent , β€” ReentrantLock, .







Loom?







Loom , Loom, , .







, , ThreadLocals. ThreadLocals, . . JDK ThreadLocals, .







SimpleDateFormat.

SimpleDateFormat , , ThreadLocals.







JDK SimpleDateFormats java.date dateformatter. ,

static final , . ThreadLocals .







. , . TCP-, . BufferedOutputStream, PrintStream - , . JDK, , .







, , java.util.concurrent .







, .







.













, ,

- . Java ( IntelliJ, NetBeans, Eclipse) JDI, wire protocol, , JVM Tool Interface JVM TI, . , .







, . , .

.







, . : «» ( ) . , . , , . JVM TI .







, , , , .







, : - , , Β« Β»? , , . , . , β€” , - , , .







.







. Java Flight Recorder Loom . , JFR , print JFR, , .







JFR.













server.jfr, . Jetty, . , . . JFR , , 200 , , , .







, . Β«virtual = trueΒ» , . , , , , java.net.url HTTP , 200 . . , JFR, .







Flight Recorder, , , JVM TI, , JVM TI, .







, , .







. , , , . , , , , , . , .







Serviceability



, .







, . , . , , , «» ( CPU), . .







β€” , . , , ? , ? ? , .







, Loom



, - . , , , .







, . , , .







, , .







API , , API, . API , , , , .







, , , , , , , , IDE , .







Preview: ARM64 Aarch64, 64- Intel ; - .









. Β« Β»: , .







, . , .







, CSP Actors. , Erlang . Java , : BlockingQueues, SynchronousQueue, , LinkedTransferQueue, .







, java.util.concurrent, . , . β€” Β«conduitsΒ», , java.nio.channels. , .







β€” . -

. . , , , .







Project Loom . , , . , . , , ExecutorService, AutoCloseable, , , , , .







, serviceability observability. , ,

. , - . , , . .







β€” . , . Java , , . . , - . . , , , , - .









:







β€” , , , .







β€” , , , Java.







, , .







, .









, Project Loom, β€” ( ) . , , . .







: https://jdk.java.net/loom


: loom-dev@openjdk.java.net


-: https://wiki.openjdk.java.net/display/loom/Main







-, β€” -.







, .







Β«Safe harborΒ»: , .













, Java- : Java- , . JPoint, ( , , VMware). , .



All Articles