闲聊 Java 线程的发展
Java 线程的东西比较多,我们以 openJDK21 为基础环境分篇章来说,本篇只是一个开篇,之后预计会细分线程篇、线程池篇和虚拟线程篇。
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 之间发展的内容可参考如下两篇文章:
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
方法执行时本身也是一个用户线程。举例来说
- 平时
t.start();
启动一个线程后,并不需要通过Thread.sleep(100);
这种方式防止main
方法这个主线程比新线程先执行完,从而导致新线程无法被执行的情况。 Thread.sleep(100);
在这时能起到的作用也就是有机会保证新线程优先于主线程执行,所以用户线程会阻止程序退出。
守护线程是后台执行的一种特殊线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程、JIT线程都是守护线程。
- 可以简单理解为守护线程服务于用户线程,当程序中只剩下守护线程,不再有用户线程时 JVM 退出,整个程序结束,所以守护线程无法阻止程序退出。
- 即
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.
除特别注明外,本站所有文章均为 windcoder 原创,转载请注明出处来自: xianliaojavaxianchengdefazhan

暂无数据