Java笔记··By/蜜汁炒酸奶

闲聊 Java 线程的发展

Java 线程的东西比较多,我们以 openJDK21 为基础环境分篇章来说,本篇只是一个开篇,之后预计会细分线程篇、线程池篇和虚拟线程篇。

Java线程发展脑图

1 Green Thread

Green Thread 是一个多对一的用户级线程库。 主要是java 1.1 和早期的 Solaris OS (2.6之前的版本)有在使用,至于三者的关系,目前仅找到了一句 Green Thread线程库是Java运行时线程和 Solaris 系统支持层的一部分

Previous to Java on Solaris 2.6 software, the Java runtime used a user-level threads library called “green threads”, part of the Java runtime thread and system support layer.

java 语言一开始就将线程作为了一个核心概念,同时宣扬可以在所有平台上运行(容器化的出现削弱了这一优势)。但在当时仍有一些平台(如 Solaris OS 2.6之前的版本)并不支持本地线程( native thread ),无法将用户线程映射到OS线程。 所以 Java 通过引入 Green Thread 这一用户级线程库来解决这种情况。说简单点就是在当时有些操作系统仍以进程为调度单位,不支持线程,所以引入了这个用户级线程库。

由于绿色线程库是用户级的,Solaris 这些操作系统认为它们都属于同一个进程(即运行该线程的 Java 程序的进程),从而 Solaris 系统一次只能处理一个绿色线程(参考前面说到的用户级线程的缺点),这也说明了 Java 在 早期 Solaris 中的线程模型是多对一的。

由于 Green Thread 已经被弃用,不再过多描述,更多关于 Solaris 与 Java 之间发展的内容可参考如下两篇文章:

  1. 《Java on Solaris 7 Developer’s Guide#Chapter 2 Multithreading》

  2. JDK 1.1 for Solaris Developer’s Guide#JVM

2 Java Thread

由上一小节可以看出来 Java 通过 Green Thread 仅是实现了并发的概念,并无法解决并行的问题,所以在 Java 1.2 以后的版本中完全被 1:1 的线程映射模型所取代了,简单来说就是在 Java 程序中每启动一个 Thread ,就会在操作系统中创建一个对应的本地线程,也就是我们在之前一篇中说的在 windows 系统中调用 WindowsAPI 来实现,在 UNIX 类系统中采用 Pthreads 来实现, 所以这里的线程也成为平台线程。

另一方面,计算机的资源是有限的,无法支持无限制创建线程,为了能够最大化利用资源,实际经常是以线程池的方式创建和使用线程。

2.1 线程类型

Java 中主要有用户线程(即 non-daemon threads,非守护线程)和守护线程( daemon threads,守护线程)这两种类型的线程。

在程序中通过 Thread 创建的线程,默认情况下是用户线程。只有所有用户线程执行完成,JVM才会退出,也就是主进程退出。main 方法执行时本身也是一个用户线程。举例来说

  1. 平时 t.start(); 启动一个线程后,并不需要通过 Thread.sleep(100); 这种方式防止 main 方法这个主线程比新线程先执行完,从而导致新线程无法被执行的情况。
  2. Thread.sleep(100); 在这时能起到的作用也就是有机会保证新线程优先于主线程执行,所以用户线程会阻止程序退出

守护线程是后台执行的一种特殊线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程JIT线程都是守护线程

  1. 可以简单理解为守护线程服务于用户线程,当程序中只剩下守护线程,不再有用户线程时 JVM 退出,整个程序结束,所以守护线程无法阻止程序退出
  2. main 方法执行完时,若只剩守护线程在执行,则程序立即结束,不会等待守护线程执行完才结束。

用户线程可通过 setDaemon(true) 方法设置为守护线程,可通过isDaemon() 方法判断是否为守护线程。

下面是JDK的Thread类中关于平台线程的部分描述

// Java线程通常是1:1内核线程

Thread supports the creation of platform threads that are typically mapped 1:1 to kernel threads scheduled by the operating system. Platform threads will usually have a large stack and other resources that are maintained by the operating system. Platforms threads are suitable for executing all types of tasks but may be a limited resource.

// 默认自动生成一个线程名

Platform threads get an automatically generated thread name by default.

// 关于守护线程与非守护线程

Platform threads are designated daemon or non-daemon threads. When the Java virtual machine starts up, there is usually one non-daemon thread (the thread that typically calls the application’s main method). The shutdown sequence begins when all started non-daemon threads have terminated. Unstarted non-daemon threads do not prevent the shutdown sequence from beginning.

// 线程优先级与线程组

In addition to the daemon status, platform threads have a thread priority and are members of a thread group.

3 Java 虚拟线程

类似 Goroutine 是 Go 的协程实现, Fibers 纤程 是 windows 对协程的实现方案,Java Virtual Thread 是 Java 中的类似实现,于 Java 19 引入预览版,Java21 升级为GA ( General availability , 一般可用)。

相对于 线程是轻量级进程,Java虚拟线程 可以称为轻量级线程,因为它是在线程中调度的。

下面是JDK的Thread类中关于虚拟线程的部分描述,具体的内容我们在后面篇章中介绍。

// 虚拟线程适合执行阻塞式任务

Thread also supports the creation of virtual threads. Virtual threads are typically user-mode threads scheduled by the Java runtime rather than the operating system. Virtual threads will typically require few resources and a single Java virtual machine may support millions of virtual threads. Virtual threads are suitable for executing tasks that spend most of the time blocked, often waiting for I/O operations to complete. Virtual threads are not intended for long running CPU intensive operations.

// 虚拟线程通常使用一小组平台线程作为载体线程。

Virtual threads typically employ a small set of platform threads used as carrier threads. Locking and I/O operations are examples of operations where a carrier thread may be re-scheduled from one virtual thread to another. Code executing in a virtual thread is not aware of the underlying carrier thread. The currentThread() method, used to obtain a reference to the current thread, will always return the Thread object for the virtual thread.

// 默认没有线程名

Virtual threads do not have a thread name by default. The getName method returns the empty string if a thread name is not set.

// 虚拟线程是守护线程

Virtual threads are daemon threads and so do not prevent the shutdown sequence from beginning. Virtual threads have a fixed thread priority that cannot be changed.

预览
Loading comments...
0 条评论

暂无数据

example
预览