一、什么是虛擬線程
虛擬線程是Java19開始增加的一個特性,和Golang的攜程類似,一個其它語言早就提供的、且如此實用且好用的功能,作為一個Java開發者,早就已經望眼欲穿了。
二、虛擬線程和普通線程的區別
“虛擬”線程,望文生義,它是“假”的,它不直接調度操作系統的線程,而是由JVM再提供一層線程的接口抽象,由普通線程調度,即一個普通的操作系統線程可以調度成千上萬個虛擬線程。
虛擬線程比普通線程的消耗要小得多得多,在內存足夠的情況下,我們甚至可以創建上百萬的虛擬線程,這在之前(Java19以前)是不可能的。
三、SpringBoot使用虛擬線程
配置
首先我們使用的Java版本是java-20.0.2-oracle,SpringBoot版本是3.1.2。
要在SpringBoot中使用虛擬線程很簡單,增加如下配置即可:
/*** 配置是用于稍后測試,spring.virtual-thread=true是使用虛擬線程,false時還是使用默認的普通線程*/
@Configuration
@ConditionalOnProperty(prefix = "spring", name = "virtual-thread", havingValue = "true")
public class ThreadConfig {@Beanpublic AsyncTaskExecutor applicationTaskExecutor() {return new TaskExecutorAdapter(Executors.newVirtualThreadPerTaskExecutor());}@Beanpublic TomcatProtocolHandlerCustomizer<?> protocolHandlerCustomizer() {return protocolHandler -> {protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());};}
}
@Async性能對比
我們寫一個異步service,里面睡眠50ms,模擬MySQL或Redis等IO操作:
@Service
public class AsyncService {/*** * @param countDownLatch 用于測試*/@Asyncpublic void doSomething(CountDownLatch countDownLatch) throws InterruptedException {Thread.sleep(50);countDownLatch.countDown();}
}
最后測試類,很簡單,就是循環調用這個方法10萬次,計算所有方法執行完成的消耗的時間:
@Test
public void testAsync() throws InterruptedException {long start = System.currentTimeMillis();int n = 100000;CountDownLatch countDownLatch = new CountDownLatch(n);for (int i = 0; i < n; i++) {asyncService.doSomething(countDownLatch);}countDownLatch.await();long end = System.currentTimeMillis();System.out.println("耗時:" + (end - start) + "ms");
}
普通線程耗時:678秒左右,超過10分鐘了
虛擬線程耗時:3.9秒!!