ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

JDK-21虚拟线程使用

JDK-21虚拟线程使用 引入1. 虚拟线程是挂载到平台线程(载体线程)中去的在遇到阻塞时载体线程将会从阻塞的虚拟线程进行卸载虚拟线程阻塞结束载体线程会挂载到空闲的载体线程上。2. 虚拟线程与平台线程相比有轻量化特点更小支持的并发量更多。3. 无需池化直接即可创建设计的目标就是避免池化。坑点1. 任务中使用 synchronized 包裹的代码则遇到阻塞会进行无法释放虚拟线程。创建虚拟线程的方式1.创建虚拟线程并且指定一个Name// 创建并启动一个虚拟线程 Thread vt Thread.ofVirtual() .name(my-vt-, 0) // 可选设置名称前缀和起始编号 .start(() - { System.out.println(Running in virtual thread); System.out.println(Is virtual: Thread.currentThread().isVirtual()); }); vt.join(); // 等待完成2. 直接创建虚拟线程书写任务逻辑// 一行代码创建并启动 Thread vt Thread.startVirtualThread(() - { System.out.println(Hello from virtual thread!); }); vt.join();3. 提交的任务都创建一个虚拟线程虚拟线程执行器// 每个提交的任务都会获得一个新的虚拟线程 try (var executor Executors.newVirtualThreadPerTaskExecutor()) { executor.submit(() - { Thread.sleep(Duration.ofSeconds(1)); return i; }) } // try-with-resources 自动关闭等待所有任务完成拓展使用1. 使用Callable进行规划任务逻辑使用虚拟线程执行器进行执行代码逻辑汇总返回结果。private static void virtualThread3() { System.out.println(创建virtualThread); long start System.currentTimeMillis(); ListCallableString tasks List.of( () - { for (int i 0; i 100; i) { System.out.println(任务1 正在被 [ Thread.currentThread() ] 执行); } // ✅ 在这里打印看看是谁在执行我 return callUserService(); }, () - { for (int i 0; i 100; i) { System.out.println(任务2 正在被 [ Thread.currentThread() ] 执行); } return callUserService(); }, () - { for (int i 0; i 100; i) { System.out.println(任务3 正在被 [ Thread.currentThread() ] 执行); } return callUserService(); } ); try (var executor Executors.newVirtualThreadPerTaskExecutor()) { ListFutureString futures executor.invokeAll(tasks); futures.stream().forEach(System.out::println); futures.stream() .map(f - { try { return f.get(); // 此时任务已完成get() 不会阻塞 } catch (Exception e) { throw new CompletionException(e); } }) .toList(); } catch (Exception e) { e.printStackTrace(); } long end System.currentTimeMillis(); System.out.println(Time taken: (end - start) / 1000 秒); System.out.println(CPU Cores: Runtime.getRuntime().availableProcessors()); }2. 使用CompletableFuture 指定虚拟线程方式进行启动private static void virtualThread5() { System.out.println(创建 virtualThread (CompletableFuture)); long start System.currentTimeMillis(); ExecutorService vtExecutor Executors.newVirtualThreadPerTaskExecutor(); // 每个任务独立提交返回 CompletableFuture CompletableFutureString f1 CompletableFuture.supplyAsync(() - { for (int i 0; i 100; i) System.out.println(任务1 [ Thread.currentThread() ]); try { return callUserService(); } catch (InterruptedException e) { throw new RuntimeException(e); } }, vtExecutor); // --- 指定虚拟线程执行器 CompletableFutureString f2 CompletableFuture.supplyAsync(() - { for (int i 0; i 100; i) System.out.println(任务2 [ Thread.currentThread() ]); try { return callUserService(); } catch (InterruptedException e) { throw new RuntimeException(e); } }, vtExecutor); CompletableFutureString f3 CompletableFuture.supplyAsync(() - { for (int i 0; i 100; i) System.out.println(任务3 [ Thread.currentThread() ]); try { return callUserService(); } catch (InterruptedException e) { throw new RuntimeException(e); } }, vtExecutor); try { // 等待所有任务完成并收集结果 ListString results CompletableFuture.allOf(f1, f2, f3) .thenApply(v - List.of(f1.join(), f2.join(), f3.join())) .join(); // 主线程阻塞等待 System.out.println(Results: results); } finally { vtExecutor.close(); // try-with-resources 也可以这里手动演示 } System.out.println(Time taken: (System.currentTimeMillis() - start) / 1000 秒); }3. 配合信号量使用private static void virtualThread4() throws RuntimeException { final Semaphore DB_LIMITER new Semaphore(50); try (var executor Executors.newVirtualThreadPerTaskExecutor()) { //先拿锁 executor.submit(() - { try { DB_LIMITER.acquire(); //业务逻辑xxx callUserService(); } catch (InterruptedException e) { //释放锁 DB_LIMITER.release(); } }); } }
返回列表