首页 > 其他分享 >JDK 21新特性---虚拟线程

JDK 21新特性---虚拟线程

时间:2023-09-28 16:15:20浏览次数:32  
标签:21 JDK Thread System --- 虚拟 线程 println out

虚拟线程是什么

  • 虚拟线程是与原来的平台线程类似的线程,它也是Java.Lang.Thread的一个实例,但它是由Jvm进行管理和调度的。
  • 与虚拟内存的实现方式类似,在Jvm中会存在一个Map来维护虚拟线程与实际系统线程的对应关系。
  • 当虚拟线程运行时,Jvm会把它分配到一个平台线程上,这个平台线程被称为Carrier。当虚拟线程遇到I/O阻塞被挂起后,这个Carrier就空闲下来,Jvm会分配其他的虚拟线程到这个Carrier上。
  • 根据虚拟线程的特性来说,它适合执行一些耗时的I/O阻塞式的任务。

虚拟线程与平台线程的区别是什么

  1. 管理与调度不同:平台线程是由OS进行管理和调度的,而虚拟线程则是由JVM进行管理与调度的。
  2. 线程规模不同:平台线程的规模受到OS的限制,而虚拟线程则没有这个限制,理论上来说虚拟线程的最大数量要比平台线程大得多。
  3. 使用成本不同:由于虚拟内存是受JVM管理的,因此它的分配不需要进行系统调用,也不受系统上下文切换的影响。

什么场景下使用虚拟线程

  • 虚拟线程适合在高并发场景下,执行可能带来长时间I/O阻塞的任务。官方给出的示例是一个Server-Client模式的例子。

     public class EchoServer {
         
         public static void main(String[] args) throws IOException {
              
             if (args.length != 1) {
                 System.err.println("Usage: java EchoServer <port>");
                 System.exit(1);
             }
              
             int portNumber = Integer.parseInt(args[0]);
             try (
                 ServerSocket serverSocket =
                     new ServerSocket(Integer.parseInt(args[0]));
             ) {                
                 while (true) {
                     Socket clientSocket = serverSocket.accept();
                     // Accept incoming connections
                     // Start a service thread
                     Thread.ofVirtual().start(() -> {
                         try (
                             PrintWriter out =
                                 new PrintWriter(clientSocket.getOutputStream(), true);
                             BufferedReader in = new BufferedReader(
                                 new InputStreamReader(clientSocket.getInputStream()));
                         ) {
                             String inputLine;
                             while ((inputLine = in.readLine()) != null) {
                                 System.out.println(inputLine);
                                 out.println(inputLine);
                             }
                         
                         } catch (IOException e) { 
                             e.printStackTrace();
                         }
                     });
                 }
             } catch (IOException e) {
                 System.out.println("Exception caught when trying to listen on port "
                     + portNumber + " or listening for a connection");
                 System.out.println(e.getMessage());
             }
         }
     }
     
     public class EchoClient {
         public static void main(String[] args) throws IOException {
             if (args.length != 2) {
                 System.err.println(
                     "Usage: java EchoClient <hostname> <port>");
                 System.exit(1);
             }
             String hostName = args[0];
             int portNumber = Integer.parseInt(args[1]);
             try (
                 Socket echoSocket = new Socket(hostName, portNumber);
                 PrintWriter out =
                     new PrintWriter(echoSocket.getOutputStream(), true);
                 BufferedReader in =
                     new BufferedReader(
                         new InputStreamReader(echoSocket.getInputStream()));
             ) {
                 BufferedReader stdIn =
                     new BufferedReader(
                         new InputStreamReader(System.in));
                 String userInput;
                 while ((userInput = stdIn.readLine()) != null) {
                     out.println(userInput);
                     System.out.println("echo: " + in.readLine());
                     if (userInput.equals("bye")) break;
                 }
             } catch (UnknownHostException e) {
                 System.err.println("Don't know about host " + hostName);
                 System.exit(1);
             } catch (IOException e) {
                 System.err.println("Couldn't get I/O for the connection to " +
                     hostName);
                 System.exit(1);
             } 
         }
     }
    

如何使用虚拟线程

官方提供了多种使用虚拟线程的方式:

  • Thread.ofVirtual()

         Thread thread = Thread.ofVirtual().start(() -> System.out.println("Hello"));
         thread.join();
    
  • Thread.Builder()

          try {
                      Thread.Builder builder = Thread.ofVirtual().name("MyThread");
                      Runnable task = () -> {
                          System.out.println("Running thread");
                      };
                      Thread t = builder.start(task);
                      System.out.println("Thread t name: " + t.getName());
                      t.join();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
    
  • Executors.newVirtualThreadPerTaskExecutor()

          try (ExecutorService myExecutor =
                      Executors.newVirtualThreadPerTaskExecutor()) {
                      Future<?> future =
                          myExecutor.submit(() -> System.out.println("Running thread"));
                      future.get();
                      System.out.println("Task completed");
                  } catch (InterruptedException | ExecutionException e) {
                      e.printStackTrace();
                  }
    

虚拟线程 VS 平台线程

  • 线程执行100个sleep 1秒的任务

          var vs = Executors.newFixedThreadPool(200);
          List<Future<Integer>> futures = new ArrayList<>();
          var begin = System.currentTimeMillis();
          for (int i = 0; i < 1000; i++) {
      	var future = vs.submit(() -> {
      		Thread.sleep(1000L);
      		return a.addAndGet(1);
      	});
      	futures.add(future);
      }
    
  • 耗时结果对比

          Platform Thread Exec time: 5050ms.
          Virtual Thread Exec time: 1039ms.
    

使用虚拟线程的注意事项

  1. 直接使用虚拟线程,而不要像使用平台线程那样进行池化。
  2. 虽然没有了OS的限制,可以创造出大量的虚拟线程,但是要注意,对于有限资源的访问(如数据库)等还是要加以限制。
  3. 避免使用synchronized阻塞操作。

标签:21,JDK,Thread,System,---,虚拟,线程,println,out
From: https://www.cnblogs.com/skysea82410/p/17735975.html

相关文章

  • 基于三菱Q系列cc-Link的卧式自动燃煤蒸汽锅炉控制系统
    系统说明: 方案选用:本系统最终采用三菱Q系列+FX3U系列方案 工艺流程: 触摸屏设计: 程序设计:本文章为原创作品,未经允许,请勿转载,否则将会追究法律责任。 ......
  • Django实战项目-学习任务系统-需求说明
    一,需求说明在我最近的阅读中,我深深被一些关于智能或系统的小说吸引。这些小说的主角意外获得某种神秘的智能或系统,然后通过完成系统发布的各种任务,逐渐提升自己的知识和能力。即使是普通的屌丝,也能在系统的管理和奖励下,一步步实现自己的梦想。这种情景让我深感兴趣,于是我......
  • ChatGLM-6B-PT微调
    目录开发环境ChatGLM2-6B源码下载模型安装依赖下载ADGEN数据集微调前修改训练步数微调后开发环境矩池云https://www.matpool.com/host-market/gpuChatGLM2-6B源码https://github.com/THUDM/ChatGLM2-6Bgitclonehttps://github.com/THUDM/ChatGLM2-6B.git下载模型......
  • Solution -「JOISC 2020」建筑装饰 4
      朴素的DP形式是定义\(f_{i,j,A/B}\)表示前\(i\)个元素选择了\(j\)个\(A\)的可达性.\(\mathcalO(n^2)\).交换状态与值域,定义\(f_{i,A/B,A/B}\)表示前\(i\)个元素中的最后一个元素(即\(i\))选择了\(A/B\),在最大化\(A/B\)的数量的目标下求得的\(......
  • 2023-2024-1 20231301 《计算机基础与程序设计》第一周学习总结
    2023-2024-120231301《计算机基础与程序设计》第一周学习总结作业信息作业链接作业课程<班级>(2023-2024-1-计算机基础与程序设计)作业要求<作业>(2023-2024-1计算机基础与程序设计第一周学习总结)作业目标<《计算机基础与程序设计》预习>《计算机基础与程序......
  • nodejs学习01-安装
    参考:nodeJS压缩版安装与配置 注意:最新版本不支持win7有问题,我win7用的 node-v11.15.0-win-x86历史版本下载:https://registry.npmmirror.com/binary.html?path=node/......
  • 21-生命周期
    生命周期生命周期又名生命周期回调函数、生命周期函数、生命周期钩子什么是生命周期Vue在关键时刻帮我们调用的一些特殊名称的函数。生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。生命周期函数中的this指向是vm或组件实例对象。 通过一个小案......
  • 麦肯锡结构化战略思维(2)- 结构化战略思维的应用
    永远不要派人类来做机器的工作。智能化的机器正在最大限度地将人们从简单而重复的工作中释放出来,所有流程化、标准化和有“正确答案”的岗位必将被机器取代。人类则应该逐渐聚焦于更复杂、更具挑战和更需要创造力的工作中。新麦肯锡五步法从项目管理的角度,串起战略项目解决从开始......
  • JAVA导入工程遇见Could not transfer artifact io.rest-assured:rest-assured:pom:4.2
    问题:用idea导入已有的工程,操作File->InvalidateCaches/Restart后,点击右上角的Run,报以下异常:“Couldnottransferartifactio.rest-assured:rest-assured:pom:4.2.0”如下图所示:解决办法:因为Maven目录配置的问题,打开File->NewProjectsSettings->SettingsforNewProjects......
  • 7.mini-batch梯度下降
    importnumpyasnpimportmatplotlib.pyplotaspltimportscipy.ioimportmathimportsklearnimportsklearn.datasetsfromopt_utilsimportload_params_and_grads,initialize_parameters,forward_propagation,backward_propagationfromopt_utilsimportcomp......