Hi, I’m Shendi
并行执行是指在操作系统中,一组程序按独立异步的速度执行,无论从微观还是宏观,程序都是一起执行的
目前 JDK 最新版本是 21,而 21 新增了虚拟线程,并行执行的几种方式有如下:
线程是操作系统调度的基本单位,允许并发执行多个任务。
Java中的线程可以通过继承Thread类或实现Runnable接口来创建。
new Thread(() -> {
// 线程启动执行
}).start();
// ...
class MyThread extends Thread {
@Override
public void run() {
// 线程启动执行
}
}
new MyThread().start();
线程是重量级的资源,创建和销毁线程需要一定的开销。线程的调度和管理由操作系统负责,因此线程的切换和同步可能会引起性能开销。频繁地创建和销毁线程会对系统性能产生负面影响。为了解决这个问题,Java提供了线程池。
异步编程是一种编程模型,它允许程序在执行某些任务时不会阻塞其他部分的执行。在Java中,异步编程可以通过使用回调函数、Future和CompletableFuture等机制来实现。
Future是JDK 1.5开始提供,CompletableFuture 是 JDK 1.8。
CompletableFuture.runAsync(() -> {
try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); }
System.out.println("run async");
}).thenAccept(r -> {
System.out.println("run async success: " + r);
});
CompletableFuture.supplyAsync(() -> {
return "supply async";
}).thenAccept(r -> {
System.out.println(r);
});
运行结果如下
在 JDK 21 中,虚拟线程正式加入。类似于其他语言的协程
与传统操作系统线程相比,虚拟线程的创建和销毁速度更快,开销更小,因此可以大量创建,更适合处理轻量级任务。虚拟线程在用户空间实现,而不是由操作系统管理。
// 直接启动虚拟线程并执行
Thread.startVirtualThread(() -> {
System.out.println("hello,world");
});
// 通过start执行
Thread.ofVirtual().unstarted(() -> {
System.out.println("hello,world");
}).start();
// 需要让主线程等待,以免虚拟线程还未执行完,程序就结束了
Thread.sleep(100);
线程是并发执行的基本单位,通常说的线程是操作系统级的线程(CPU线程 -> 操作系统线程 -> Java线程)
线程的数量是有限的,通常一个CPU核心只有一个CPU线程,但通过超线程技术,可以有两个或多个,而操作系统线程基于CPU线程,通过不停切换的方式可以实现n个线程。所以线程是重量级的,大量的线程会导致并发变得非常少(之前写过一个web服务器,通过直接 new Thread 的方式,没有用线程池,压测,慢慢的只有十多秒才能处理下一个请求!)
异步编程是一种编程范式,允许程序在执行耗时操作时不会阻塞主线程,而是通过回调、Future 或CompletableFuture等机制来处理异步操作的结果。异步编程的核心思想是将耗时的操作放在单独的线程中,让主线程继续执行其他任务,从而实现并发处理和异步执行。
Java的异步编程是基于多线程的,但并不限于多线程,这种编程范式可以提高程序的性能和响应速度,特别是在处理耗时操作时。
虚拟线程是Java平台上的轻量级线程实现,是Java 19引入的特性,在 21 正式加入,虚拟线程基于操作系统级别的线程,多个虚拟线程可能就使用一个操作系统级别的线程,这样就有效的减少了线程的切换。例如有两个虚拟线程执行,只有一个操作系统线程,A执行耗时的操作的时候(IO等耗时操作),就去执行B虚拟线程,线程是没有切换的,这样减少了开销,增加了并发。
END