{"id":57418,"date":"2023-05-22T16:41:01","date_gmt":"2023-05-22T11:11:01","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=57418"},"modified":"2024-01-02T17:41:22","modified_gmt":"2024-01-02T12:11:22","slug":"embracing-virtual-threads-in-spring-boot","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/embracing-virtual-threads-in-spring-boot\/","title":{"rendered":"Embracing Virtual Threads in Spring Boot"},"content":{"rendered":"<figure class=\"kz la lb lc ld le kw kx paragraph-image\">\n<div class=\"lf lg eb lh bg li\" role=\"button\">\n<div class=\"kw kx ky\"><img decoding=\"async\" loading=\"lazy\" class=\"bg lj lk c\" role=\"presentation\" src=\"\/blog\/wp-ttn-blog\/uploads\/2024\/01\/1swGL-XtmORi9ck2QqnR9wQ.png\" alt=\"\" width=\"700\" height=\"338\" \/><\/div>\n<\/div>\n<\/figure>\n<p id=\"c381\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">In this blog, we will see how we can take leverage of project loom virtual threads in spring-boot. We will also do some load testing with the help of\u00a0<strong class=\"ln fp\">JMeter<\/strong> and see how response time is for both virtual threads and normal threads.<\/p>\n<p id=\"e6e0\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Let\u2019s quickly setup our spring boot project.<\/p>\n<pre><span class=\"hljs-meta\">&lt;?xml version=<span class=\"hljs-string\">\"1.0\"<\/span> encoding=<span class=\"hljs-string\">\"UTF-8\"<\/span>?&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">project<\/span> <span class=\"hljs-attr\">xmlns<\/span>=<span class=\"hljs-string\">\"http:\/\/maven.apache.org\/POM\/4.0.0\"<\/span> <span class=\"hljs-attr\">xmlns:xsi<\/span>=<span class=\"hljs-string\">\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"<\/span>\r\n<span class=\"hljs-attr\">xsi:schemaLocation<\/span>=<span class=\"hljs-string\">\"http:\/\/maven.apache.org\/POM\/4.0.0 https:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\"<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<\/span><mark class=\"ada aba ao\"><span class=\"hljs-tag\"><span class=\"hljs-name\">modelVersion<\/span><\/span><\/mark><span class=\"hljs-tag\">&gt;<\/span>4.0.0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">modelVersion<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">parent<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-parent<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>3.1.0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">relativePath<\/span>\/&gt;<\/span> <span class=\"hljs-comment\">&lt;!-- lookup parent from repository --&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">parent<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.anil<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>virtualthread<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>0.0.1-SNAPSHOT<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">name<\/span>&gt;<\/span>virtualthread<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">name<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">description<\/span>&gt;<\/span>virtualthread<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">description<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">properties<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">java.version<\/span>&gt;<\/span>20<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">java.version<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tomcat.version<\/span>&gt;<\/span>11.0.0-M4<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">tomcat.version<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">properties<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependencies<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-data-jpa<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-comment\">&lt;!-- https:\/\/mvnrepository.com\/artifact\/org.apache.commons\/commons-lang3 --&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.apache.commons<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>commons-lang3<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>3.12.0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-comment\">&lt;!-- https:\/\/mvnrepository.com\/artifact\/mysql\/mysql-connector-java --&gt;<\/span>\r\n\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>mysql<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>mysql-connector-java<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">scope<\/span>&gt;<\/span>runtime<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">scope<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>8.0.33<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n\r\n\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-web<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-test<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">scope<\/span>&gt;<\/span>test<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">scope<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.projectlombok<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>lombok<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>1.18.24<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">scope<\/span>&gt;<\/span>compile<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">scope<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependencies<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">build<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">plugins<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">plugin<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-maven-plugin<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">plugin<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">plugin<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.apache.maven.plugins<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>maven-compiler-plugin<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">configuration<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">compilerArgs<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">arg<\/span>&gt;<\/span>--enable-preview<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">arg<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">compilerArgs<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">source<\/span>&gt;<\/span>20<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">source<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span>&gt;<\/span>20<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">configuration<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">plugin<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">plugins<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">build<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">project<\/span>&gt;<\/span>\r\n\r\n<\/pre>\n<p id=\"6d11\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">We need to enable preview features since Project Loom is in the preview stage. We have to wait for Java 21\u2019s release for it to become a final feature.<\/p>\n<pre class=\"mj mk ml mm mn mo mp mq bo mr ms mt\"><span id=\"8b37\" class=\"mu mv fo mp b bf mw mx l my mz\" data-selectable-paragraph=\"\">package org.<span class=\"hljs-property\">anil<\/span>.<span class=\"hljs-property\">virtualthread<\/span>;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> lombok.<span class=\"hljs-property\">extern<\/span>.<span class=\"hljs-property\">slf4j<\/span>.<span class=\"hljs-property\">Slf4j<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> org.<span class=\"hljs-property\">springframework<\/span>.<span class=\"hljs-property\">boot<\/span>.<span class=\"hljs-property\">SpringApplication<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> org.<span class=\"hljs-property\">springframework<\/span>.<span class=\"hljs-property\">boot<\/span>.<span class=\"hljs-property\">autoconfigure<\/span>.<span class=\"hljs-property\">SpringBootApplication<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> org.<span class=\"hljs-property\">springframework<\/span>.<span class=\"hljs-property\">boot<\/span>.<span class=\"hljs-property\">web<\/span>.<span class=\"hljs-property\">embedded<\/span>.<span class=\"hljs-property\">tomcat<\/span>.<span class=\"hljs-property\">TomcatProtocolHandlerCustomizer<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> org.<span class=\"hljs-property\">springframework<\/span>.<span class=\"hljs-property\">context<\/span>.<span class=\"hljs-property\">annotation<\/span>.<span class=\"hljs-property\">Bean<\/span>;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> java.<span class=\"hljs-property\">util<\/span>.<span class=\"hljs-property\">concurrent<\/span>.<span class=\"hljs-property\">Executors<\/span>;\r\n\r\n<span class=\"hljs-meta\">@SpringBootApplication<\/span>\r\n<span class=\"hljs-meta\">@Slf4j<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title.class\">VirtualthreadApplication<\/span> {\r\n\r\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-built_in\">void<\/span> <span class=\"hljs-title.function\">main<\/span>(<span class=\"hljs-params\"><span class=\"hljs-built_in\">String<\/span>[] args<\/span>) {\r\n        <span class=\"hljs-title.class\">SpringApplication<\/span>.<span class=\"hljs-title.function\">run<\/span>(<span class=\"hljs-title.class\">VirtualthreadApplication<\/span>.<span class=\"hljs-property\">class<\/span>, args);\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Bean<\/span>\r\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title.class\">TomcatProtocolHandlerCustomizer<\/span>&lt;?&gt; <span class=\"hljs-title.function\">protocolHandlerVirtualThreadExecutorCustomizer<\/span>() {\r\n        <span class=\"hljs-keyword\">return<\/span> protocolHandler -&gt; {\r\n            log.<span class=\"hljs-title.function\">info<\/span>(<span class=\"hljs-string\">\"Configuring \"<\/span> + protocolHandler + <span class=\"hljs-string\">\" to use VirtualThreadPerTaskExecutor\"<\/span>);\r\n            protocolHandler.<span class=\"hljs-title.function\">setExecutor<\/span>(<span class=\"hljs-title.class\">Executors<\/span>.<span class=\"hljs-title.function\">newVirtualThreadPerTaskExecutor<\/span>());\r\n        };\r\n    }\r\n\r\n}<\/span><\/pre>\n<p id=\"6456\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">As of now, we need to configure virtual thread settings for the Tomcat server. In the future, this may be taken care of in auto-configuration itself.<\/p>\n<pre class=\"mj mk ml mm mn mo mp mq bo mr ms mt\"><span id=\"3ee4\" class=\"mu mv fo mp b bf mw mx l my mz\" data-selectable-paragraph=\"\"><span class=\"hljs-keyword\">package<\/span> org.anil.virtualthread;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> org.apache.commons.lang3.RandomStringUtils;\r\n<span class=\"hljs-keyword\">import<\/span> org.apache.commons.lang3.RandomUtils;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.beans.factory.annotation.Autowired;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.web.bind.annotation.GetMapping;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.web.bind.annotation.PostMapping;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.web.bind.annotation.RestController;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> java.util.List;\r\n\r\n<span class=\"hljs-meta\">@RestController<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title.class\">HomeController<\/span> {\r\n\r\n    <span class=\"hljs-meta\">@Autowired<\/span>\r\n    ProductRepository productRepository;\r\n\r\n\r\n    <span class=\"hljs-meta\">@GetMapping(\"\/thread\")<\/span>\r\n    <span class=\"hljs-keyword\">public<\/span> List&lt;Product&gt; <span class=\"hljs-title.function\">checkThread<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> InterruptedException {\r\n        Thread.sleep(<span class=\"hljs-number\">1000<\/span>);\r\n        <span class=\"hljs-keyword\">return<\/span> productRepository.findAll();\r\n    }\r\n\r\n\r\n    <span class=\"hljs-meta\">@PostMapping(\"\/save\")<\/span>\r\n    <span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title.function\">saveProduct<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> InterruptedException {\r\n        <span class=\"hljs-keyword\">for<\/span>(<span class=\"hljs-type\">int<\/span> i=<span class=\"hljs-number\">0<\/span>; i&lt; <span class=\"hljs-number\">1000<\/span>; i++){\r\n            <span class=\"hljs-type\">Product<\/span> <span class=\"hljs-variable\">product<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title.class\">Product<\/span>();\r\n            product.setProductName(RandomStringUtils.randomAlphanumeric(<span class=\"hljs-number\">5<\/span>));\r\n            product.setPrice(RandomUtils.nextLong(<span class=\"hljs-number\">10<\/span>,<span class=\"hljs-number\">1000<\/span>));\r\n            product.setPrice(<span class=\"hljs-number\">1L<\/span>);\r\n            productRepository.save(product);\r\n        }\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"anil\"<\/span>;\r\n    }\r\n}<\/span><\/pre>\n<p id=\"4b5e\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">We have a\u00a0<strong class=\"ln fp\">GetMapping<\/strong>\u00a0that returns all the products; we have 1000\u00a0<strong class=\"ln fp\">Products<\/strong>\u00a0in our database.<\/p>\n<p>We have made our thread sleep for 1 second. Let\u2019s see our\u00a0<strong class=\"ln fp\">Product<\/strong> entity and <b>product repository<\/b>\u00a0as well.<\/p>\n<pre class=\"mj mk ml mm mn mo mp mq bo mr ms mt\"><span id=\"a980\" class=\"mu mv fo mp b bf mw mx l my mz\" data-selectable-paragraph=\"\"><span class=\"hljs-keyword\">package<\/span> org.anil.virtualthread;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> jakarta.persistence.Entity;\r\n<span class=\"hljs-keyword\">import<\/span> jakarta.persistence.GeneratedValue;\r\n<span class=\"hljs-keyword\">import<\/span> jakarta.persistence.GenerationType;\r\n<span class=\"hljs-keyword\">import<\/span> jakarta.persistence.Id;\r\n<span class=\"hljs-keyword\">import<\/span> lombok.Getter;\r\n<span class=\"hljs-keyword\">import<\/span> lombok.Setter;\r\n\r\n<span class=\"hljs-meta\">@Entity<\/span>\r\n<span class=\"hljs-meta\">@Getter<\/span>\r\n<span class=\"hljs-meta\">@Setter<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title.class\">Product<\/span> {\r\n    <span class=\"hljs-meta\">@Id<\/span>\r\n    <span class=\"hljs-meta\">@GeneratedValue(strategy = GenerationType.IDENTITY)<\/span>\r\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-built_in\">Long<\/span> id;\r\n    <span class=\"hljs-keyword\">private<\/span> String productName;\r\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-built_in\">Long<\/span> price;\r\n}<\/span><\/pre>\n<pre class=\"na mo mp mq bo mr ms mt\"><span id=\"8fd2\" class=\"mu mv fo mp b bf mw mx l my mz\" data-selectable-paragraph=\"\"><span class=\"hljs-keyword\">package<\/span> org.anil.virtualthread;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.data.jpa.repository.JpaRepository;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title.class\">ProductRepository<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title.class\">JpaRepository<\/span>&lt;Product,Long&gt; {\r\n}<\/span><\/pre>\n<p id=\"461b\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Let\u2019s see our application.yaml<\/p>\n<pre class=\"mj mk ml mm mn mo mp mq bo mr ms mt\"><span id=\"3a9a\" class=\"mu mv fo mp b bf mw mx l my mz\" data-selectable-paragraph=\"\"><span class=\"hljs-attr\">spring:<\/span>\r\n  <span class=\"hljs-attr\">datasource:<\/span>\r\n    <span class=\"hljs-attr\">driver-class-name:<\/span> <span class=\"hljs-string\">com.mysql.cj.jdbc.Driver<\/span>\r\n    <span class=\"hljs-attr\">maxIdle:<\/span> <span class=\"hljs-number\">1<\/span>\r\n    <span class=\"hljs-attr\">timeBetweenEvictionRunsMillis:<\/span> <span class=\"hljs-number\">60000<\/span>\r\n    <span class=\"hljs-attr\">hikari:<\/span>\r\n      <span class=\"hljs-attr\">connection-timeout:<\/span> <span class=\"hljs-number\">60000<\/span>\r\n      <span class=\"hljs-attr\">maximum-pool-size:<\/span> <span class=\"hljs-number\">10<\/span>\r\n      <span class=\"hljs-attr\">minimum-idle:<\/span> <span class=\"hljs-number\">5<\/span>\r\n    <span class=\"hljs-attr\">url:<\/span> <span class=\"hljs-string\">jdbc:mysql:\/\/localhost:3306\/todos<\/span>\r\n    <span class=\"hljs-attr\">testWhileIdle:<\/span> <span class=\"hljs-literal\">true<\/span>\r\n    <span class=\"hljs-attr\">username:<\/span> <span class=\"hljs-string\">root<\/span>\r\n    <span class=\"hljs-attr\">password:<\/span> <span class=\"hljs-string\">root1234<\/span>\r\n    <span class=\"hljs-attr\">validationQuery:<\/span> <span class=\"hljs-string\">SELECT<\/span> <span class=\"hljs-number\">1<\/span>\r\n  <span class=\"hljs-attr\">flyway:<\/span>\r\n    <span class=\"hljs-attr\">baseline-version:<\/span> <span class=\"hljs-number\">0<\/span>\r\n    <span class=\"hljs-attr\">enabled:<\/span> <span class=\"hljs-literal\">true<\/span>\r\n    <span class=\"hljs-attr\">validate-on-migrate:<\/span> <span class=\"hljs-literal\">false<\/span>\r\n  <span class=\"hljs-attr\">jpa:<\/span>\r\n    <span class=\"hljs-attr\">database:<\/span> <span class=\"hljs-string\">mysql<\/span>\r\n    <span class=\"hljs-attr\">generate-ddl:<\/span> <span class=\"hljs-literal\">true<\/span>\r\n    <span class=\"hljs-attr\">hibernate:<\/span>\r\n      <span class=\"hljs-attr\">ddl-auto:<\/span> <span class=\"hljs-string\">none<\/span>\r\n      <span class=\"hljs-attr\">format_sql:<\/span> <span class=\"hljs-literal\">true<\/span>\r\n    <span class=\"hljs-attr\">show-sql:<\/span> <span class=\"hljs-literal\">true<\/span><\/span><\/pre>\n<p id=\"9024\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Let\u2019s first run the application by commenting on the following line: This will run our application on normal threads.<\/p>\n<pre class=\"mj mk ml mm mn mo mp mq bo mr ms mt\"><span id=\"2139\" class=\"mu mv fo mp b bf mw mx l my mz\" data-selectable-paragraph=\"\"><span class=\"hljs-keyword\">package<\/span> org.anil.virtualthread;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> lombok.extern.slf4j.Slf4j;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.boot.SpringApplication;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.boot.autoconfigure.SpringBootApplication;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Bean;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> java.util.concurrent.Executors;\r\n\r\n<span class=\"hljs-meta\">@SpringBootApplication<\/span>\r\n<span class=\"hljs-meta\">@Slf4j<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title.class\">VirtualthreadApplication<\/span> {\r\n\r\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title.function\">main<\/span><span class=\"hljs-params\">(String[] args)<\/span> {\r\n        SpringApplication.run(VirtualthreadApplication.class, args);\r\n    }\r\n\r\n<span class=\"hljs-comment\">\/\/    @Bean<\/span>\r\n<span class=\"hljs-comment\">\/\/    public TomcatProtocolHandlerCustomizer&lt;?&gt; protocolHandlerVirtualThreadExecutorCustomizer() {<\/span>\r\n<span class=\"hljs-comment\">\/\/        return protocolHandler -&gt; {<\/span>\r\n<span class=\"hljs-comment\">\/\/            log.info(\"Configuring \" + protocolHandler + \" to use VirtualThreadPerTaskExecutor\");<\/span>\r\n<span class=\"hljs-comment\">\/\/            protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());<\/span>\r\n<span class=\"hljs-comment\">\/\/        };<\/span>\r\n<span class=\"hljs-comment\">\/\/    }<\/span>\r\n}<\/span><\/pre>\n<p id=\"2334\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Now let\u2019s setup our\u00a0<strong class=\"ln fp\">JMeter<\/strong>. We will have 1000 requests, which will ramp up in 3 seconds. And it will continue like this for a duration of 200 seconds. Every 3 seconds, 1000 GET (\u201c\/thread\u201d) requests will be fired. We have also added a Response Time Graph Listener.<\/p>\n<figure class=\"mj mk ml mm mn le kw kx paragraph-image\">\n<div class=\"lf lg eb lh bg li\" role=\"button\">\n<div class=\"kw kx nb\"><img decoding=\"async\" loading=\"lazy\" class=\"bg lj lk c\" role=\"presentation\" src=\"\/blog\/wp-ttn-blog\/uploads\/2024\/01\/1xWO_ONIa7Ohs_rq419SqGg.png\" alt=\"\" width=\"700\" height=\"389\" \/><\/div>\n<\/div>\n<\/figure>\n<p id=\"e9aa\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Now let\u2019s run our test and wait for 200 seconds.<\/p>\n<figure class=\"mj mk ml mm mn le kw kx paragraph-image\">\n<div class=\"lf lg eb lh bg li\" role=\"button\">\n<div class=\"kw kx nc\"><img decoding=\"async\" loading=\"lazy\" class=\"bg lj lk c\" role=\"presentation\" src=\"\/blog\/wp-ttn-blog\/uploads\/2024\/01\/1B_asy37c3Soy7xt2nmxPdQ.png\" alt=\"\" width=\"700\" height=\"452\" \/><\/div>\n<\/div>\n<\/figure>\n<p id=\"5292\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">In the graph, we can see that once the entire thread pool of Tomcat is utilised, the response time shoots from 3600 ms to 5200 ms. Since then, it has remained like that only as previous threads are released.<\/p>\n<p id=\"ff73\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Now let\u2019s run a load test with the virtual thread feature enabled.<\/p>\n<pre class=\"mj mk ml mm mn mo mp mq bo mr ms mt\"><span id=\"048c\" class=\"mu mv fo mp b bf mw mx l my mz\" data-selectable-paragraph=\"\">package org.<span class=\"hljs-property\">anil<\/span>.<span class=\"hljs-property\">virtualthread<\/span>;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> lombok.<span class=\"hljs-property\">extern<\/span>.<span class=\"hljs-property\">slf4j<\/span>.<span class=\"hljs-property\">Slf4j<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> org.<span class=\"hljs-property\">springframework<\/span>.<span class=\"hljs-property\">boot<\/span>.<span class=\"hljs-property\">SpringApplication<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> org.<span class=\"hljs-property\">springframework<\/span>.<span class=\"hljs-property\">boot<\/span>.<span class=\"hljs-property\">autoconfigure<\/span>.<span class=\"hljs-property\">SpringBootApplication<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> org.<span class=\"hljs-property\">springframework<\/span>.<span class=\"hljs-property\">boot<\/span>.<span class=\"hljs-property\">web<\/span>.<span class=\"hljs-property\">embedded<\/span>.<span class=\"hljs-property\">tomcat<\/span>.<span class=\"hljs-property\">TomcatProtocolHandlerCustomizer<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> org.<span class=\"hljs-property\">springframework<\/span>.<span class=\"hljs-property\">context<\/span>.<span class=\"hljs-property\">annotation<\/span>.<span class=\"hljs-property\">Bean<\/span>;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> java.<span class=\"hljs-property\">util<\/span>.<span class=\"hljs-property\">concurrent<\/span>.<span class=\"hljs-property\">Executors<\/span>;\r\n\r\n<span class=\"hljs-meta\">@SpringBootApplication<\/span>\r\n<span class=\"hljs-meta\">@Slf4j<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title.class\">VirtualthreadApplication<\/span> {\r\n\r\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-built_in\">void<\/span> <span class=\"hljs-title.function\">main<\/span>(<span class=\"hljs-params\"><span class=\"hljs-built_in\">String<\/span>[] args<\/span>) {\r\n        <span class=\"hljs-title.class\">SpringApplication<\/span>.<span class=\"hljs-title.function\">run<\/span>(<span class=\"hljs-title.class\">VirtualthreadApplication<\/span>.<span class=\"hljs-property\">class<\/span>, args);\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Bean<\/span>\r\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title.class\">TomcatProtocolHandlerCustomizer<\/span>&lt;?&gt; <span class=\"hljs-title.function\">protocolHandlerVirtualThreadExecutorCustomizer<\/span>() {\r\n        <span class=\"hljs-keyword\">return<\/span> protocolHandler -&gt; {\r\n            log.<span class=\"hljs-title.function\">info<\/span>(<span class=\"hljs-string\">\"Configuring \"<\/span> + protocolHandler + <span class=\"hljs-string\">\" to use VirtualThreadPerTaskExecutor\"<\/span>);\r\n            protocolHandler.<span class=\"hljs-title.function\">setExecutor<\/span>(<span class=\"hljs-title.class\">Executors<\/span>.<span class=\"hljs-title.function\">newVirtualThreadPerTaskExecutor<\/span>());\r\n        };\r\n    }\r\n\r\n}<\/span><\/pre>\n<p id=\"e6c8\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Now let\u2019s run our test and wait for 200 seconds.<\/p>\n<figure class=\"mj mk ml mm mn le kw kx paragraph-image\">\n<div class=\"lf lg eb lh bg li\" role=\"button\">\n<div class=\"kw kx nd\"><img decoding=\"async\" loading=\"lazy\" class=\"bg lj lk c\" role=\"presentation\" src=\"\/blog\/wp-ttn-blog\/uploads\/2024\/01\/1YdDdj1lIJaIPP42vV-di7w.png\" alt=\"\" width=\"700\" height=\"455\" \/><\/div>\n<\/div>\n<\/figure>\n<p id=\"d5da\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Clearly, now the response time for concurrent 1000 requests is nearly just above 1000 ms and at some point, shoots up to 1400 seconds, which is far better than when we were using normal threads.<\/p>\n<p id=\"9169\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Clearly, when we need to utilise the underlying CPU to the fullest, we should start embracing virtual threads in our application, and suddenly we can see that the throughput of our application has increased manifold for the same hardware.<\/p>\n<p id=\"fa39\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">This is much better than switching to reactive programming, which means rewriting all your code, which is very hard to maintain and even harder to debug.<\/p>\n<p id=\"c050\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Simply put, more users can use the application and get their response simultaneously as the first user.<\/p>\n<p id=\"7cfa\" class=\"pw-post-body-paragraph ll lm fo ln b lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi fh bj\" data-selectable-paragraph=\"\">Looking for in-depth analysis and expert opinions? Check out our other<a href=\"https:\/\/www.tothenew.com\/insights\"> resources<\/a> now.<\/p>\n<p data-selectable-paragraph=\"\">The original post link is <a href=\"https:\/\/medium.com\/@anil.java.story\/embracing-virtual-threads-in-spring-boot-4140d3b8a5a\">https:\/\/medium.com\/@anil.java.story\/embracing-virtual-threads-in-spring-boot-4140d3b8a5a<\/a><\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>In this blog, we will see how we can take leverage of project loom virtual threads in spring-boot. We will also do some load testing with the help of\u00a0JMeter and see how response time is for both virtual threads and normal threads. Let\u2019s quickly setup our spring boot project. &lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt; &lt;project xmlns=&#8221;http:\/\/maven.apache.org\/POM\/4.0.0&#8243; xmlns:xsi=&#8221;http:\/\/www.w3.org\/2001\/XMLSchema-instance&#8221; [&hellip;]<\/p>\n","protected":false},"author":1520,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":58},"categories":[446],"tags":[1202,5234],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/57418"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1520"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=57418"}],"version-history":[{"count":4,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/57418\/revisions"}],"predecessor-version":[{"id":59695,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/57418\/revisions\/59695"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=57418"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=57418"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=57418"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}