Java中并行执行的三种方式:线程、异步编程、虚拟线程

2023-12-18 06:25:00

Hi, I’m Shendi


Java中并行执行的三种方式:线程、异步编程、虚拟线程




Java并行执行的几种方式

并行执行是指在操作系统中,一组程序按独立异步的速度执行,无论从微观还是宏观,程序都是一起执行的


目前 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

文章来源:https://blog.csdn.net/qq_41806966/article/details/135052995
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。