06.深入学习Java 线程

1 线程的状态/生命周期

        Java 的 Thread 类对线程状态进行了枚举:

public class Thread implements Runnable {
    
    public enum State {
        NEW,
        RUNNABLE,
        BLOCKED,
        WAITING,
        TIMED_WAITING,
        TERMINATED;
    }
}
  1. 初始(NEW):新创建了一个线程对象,但还没有调用 start()方法。
  2. 运行(RUNNABLE):Java 线程中将就绪(ready)和运行中(running)两种  状态笼统的称为“运行”。
    1. 线程对象创建后,其他线程(比如 main 线程)调用了该对象的start()方法。  该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU 的使用权, 此时处于就绪状态(ready)。就绪状态的线程在获得 CPU 时间片后变为运行中状态(Running)。
  3. 阻塞(BLOCKED):表示线程阻塞于锁。
  4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作  (通知或中断)。
  5. 超时等待(TIMED_WAITING):该状态不同于 WAITING,它可以在指定的时间后自行返回。
  6. 终止(TERMINATED):表示该线程已经执行完毕。

        线程状态之间的变迁如下图所示:

2 线程的调度

        线程的状态的变迁是因为存在线程调度。

        线程调度是指系统为线程分配 CPU 使用权的过程,主要调度方式有两种:

  • 协同式线程调度(Cooperative Threads-Scheduling)。
  • 抢占式线程调度(Preemptive Threads-Scheduling)。

        使用协同式线程调度的多线程系统,线程执行的时间由线程本身来控制,线程把自己的工作执行完之后,要主动通知系统切换到另外一个线程上。使用协同式线程调度的最大好处是实现简单,由于线程要把自己的事情做完后才会通知系统进行线程切换,所以没有线程同步的问题,但是坏处也很明显,如果一个线程出了问题,则程序就会一直阻塞。

        使用抢占式线程调度的多线程系统,每个线程执行的时间以及是否切换都由系统决定。在这种情况下,线程的执行时间不可控,所以不会有「一个线程导致整个进程阻塞」的问题出现。

2.1 Java 线程调度就是抢占式调度

        为什么Java 线程调度是抢占式调度?这需要我们了解 Java 中线程的实现模式。

        我们已经知道线程其实是操作系统层面的实体,Java 中的线程怎么和操作系统层面对应起来呢?

        任何语言实现线程主要有三种方式:使用内核线程实现(1:1 实现),使用用户线程实现(1:N 实现),使用用户线程加轻量级进程混合实现(N:M 实现)。

2.1.1 内核线程实现

        使用内核线程实现的方式也被称为1:1 实现。内核线程(Kernel-Level  Thread, KLT) 就是直接由操作系统内核(Kernel, 下称内核)支持的线程。

        这种线程由内核来完成线程切换,内核通过操纵调度器(Scheduler) 对线程进行调度,并负责将线程的任务映射到各个处理器上。

        由于内核线程的支持,每个线程都成为一个独立的调度单元,即使其中某一个在系统调用中被阻塞了,也不会影响整个进程继续工作,相关的调度工作也不需要额外考虑,已经由操作系统处理了。

        局限性:首先,由于是基于内核线程实现的,所以各种线程操作,如创建、 析构及同步,都需要进行系统调用。而系统调用的代价相对较高,需要在用户态(User Mode)和内核态(Kernel Mode)中来回切换。其次,每个语言层面的线程都需要有一个内核线程的支持,因此要消耗一定的内核资源(如内核线程的栈空间),因此一个系统支持的线程数量是有限的。

2.1.2 用户线程实现

        严格意义上的用户线程指的是完全建立在用户空间的线程库上,系统内核不能感知到用户线程的存在及如何实现的。用户线程的建立、同步、销毁和调度完全在用户态中完成,不需要内核的帮助。如果程序实现得当,这种线程不需要切换到内核态,因此操作可以是非常快速且低消耗的,也能够支持规模更大的线程数量,部分高性能数据库中的多线程就是由用户线程实现的。

        用户线程的优势在于不需要系统内核支援,劣势也在于没有系统内核的支援,所有的线程操作都需要由用户程序自己去处理。线程的创建、销毁、切换和调度都是用户必须考虑的问题,而且由于操作系统只把处理器资源分配到进程,那诸如“阻塞如何处理”“多处理器系统中如何将线程映射到其他处理器上”这类问 题解决起来将会异常困难,甚至有些是不可能实现的。因为使用用户线程实现的程序通常都比较复杂,所以一般的应用程序都不倾向使用用户线程。Java 语言曾经使用过用户线程,最终又放弃了。但是近年来许多新的、以高并发为卖点的编程语言又普遍支持了用户线程,譬如Golang。

2.1.3 混合实现

        线程除了依赖内核线程实现和完全由用户程序自己实现之外,还有一种将内核线程与用户线程一起使用的实现方式,被称为 N:M 实现。在这种混合实 现下,既存在用户线程,也存在内核线程。

        用户线程还是完全建立在用户空间中,因此用户线程的创建、切换、析构等操作依然廉价,并且可以支持大规模的用户线程并发。

        同样又可以使用内核提供的线程调度功能及处理器映射,并且用户线程的系统调用要通过内核线程来完成。在这种混合模式中,用户线程与轻量级进程的数量比是不定的,是 N:M 的关系。

2.1.4 Java 线程的实现

        Java 线程在早期的Classic 虚拟机上(JDK 1.2 以前),是用户线程实现的, 但从JDK 1.3 起,主流商用 Java 虚拟机的线程模型普遍都被替换为基于操作系统原生线程模型来实现,即采用1:1 的线程模型。

        以 HotSpot 为例,它的每一个 Java 线程都是直接映射到一个操作系统原生线程来实现的,而且中间没有额外的间接结构,所以 HotSpot 自己是不会去干涉线程调度的,全权交给底下的操作系统去处理。

        所以,这就是我们说 Java 线程调度是抢占式调度的原因。而且Java 中的线程优先级是通过映射到操作系统的原生线程上实现的,所以线程的调度最终取决于操作系统,操作系统中线程的优先级有时并不能和 Java 中的一一对应,所以 Java 优先级并不是特别靠谱。

3 线程的优先级

        在Java 线程中,通过一个整型成员变量 priority 来控制优先级,优先级的范 围从1~10,在线程构建的时候可以通过 setPriority(int)方法来修改优先级,默认优先级是5,优先级高的线程分配时间片的数量要多于优先级低的线程。

        设置线程优先级时,针对频繁阻塞(休眠或者I/O 操作)的线程需要设置较高优先级,而偏重计算(需要较多CPU 时间或者偏运算)的线程则设置较低的优先级,确保处理器不会被独占。这只是相对应的理论,实际上,在不同的JVM 以及操作系统上,线程规划会存在差异,有些操作系统甚至会忽略对线程优先级的设定。通过上面对线程调度的分析我们就可以得出的结论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/660277.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STL库--priority_queue

目录 priority_queue定义 prority_queue容器内元素的访问 priority_queue()常用函数实例解析 priority_queue内元素优先级的设置 priority_queue的常见用途 priority_queue又称为优先队列,其底层是用堆来进行实现的。在优先队列中,队首元素一定是当…

latex中伪代码后面多出=0

这latex简直就是憨猪!!! \usepackage{algpseudocode} 注释掉,或者删除就可以了 还有,引用包的时候一般begin{}中括号里是什么就引入什么包。 这下面这几行,开始全爆红说没定义,我就去一行一行问…

代码助手之-百度Comate智能体验

简介 越来越多的厂商提供了智能代码助手,百度也不例外。Baidu Comate(智能代码助手)是基于文心大模型,Comate取自Coding Mate,寓意大家的AI编码伙伴。Comate融合了百度内部多年积累的编程现场大数据和外部开源代码和知…

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第26节-内嵌blender展厅

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第26节-内嵌blender展厅 使用dtns.network德塔世界(开源的智体世界引擎),策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界…

【机器学习-k近邻算法-01】 | Scikit-Learn工具包进阶指南:机器学习sklearn.neighbors模块之k近邻算法实战

🎩 欢迎来到技术探索的奇幻世界👨‍💻 📜 个人主页:一伦明悦-CSDN博客 ✍🏻 作者简介: C软件开发、Python机器学习爱好者 🗣️ 互动与支持:💬评论 &…

轧钢测径仪分析软件,四大图表带来产线新视角!

轧钢测径仪是智能化检测设备,除了测径仪主体外,还配有测控软件系统,从这里可对测径仪进行各种设置,亦可从此观测到测径仪获得的各种信息,如检测信息、分析图表、计算尺寸、历史数据等。而从测径仪获得的图表信息主要有…

springboot课程题库管理系统-计算机毕业设计源码30812

摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于课程题库管理系统 当然也不能排除在外,随着网络技术的不断成熟,带动了课程题库管理系统 ,它彻底改变了…

【Java】HOT100+代码随想录:动态规划(下)

目录 三、打家劫舍 LeetCode198:打家劫舍 LeetCode213:打家劫舍ii LeetCode337:打家劫舍iii(树形) 四、股票问题 时间不多了,其他的先不写了 LeetCode121:买卖股票的最佳时机 五、子序列…

opencv进阶 ——(六)图像处理之图像增强

图像增强算法的目的是改善图像的视觉质量,使其更易于分析或增强特定特征。以下是一些常见的图像增强技术及其基本原理: 直方图均衡化: 直方图均衡化通过重新映射像素值来扩展图像的动态范围,使得图像的灰度级分布更加均匀。这通常…

Pandas-中axis的用法

在Pandas中,min(axis)方法是计算DataFrame或Series中每行或每列的最小值的函数。该函数可以接受一个参数axis,用于指定计算最小值的方向。当axis0时,表示沿着行的方向计算最小值;当axis1时,表示沿着列的方向计算最小值…

使用 Ubuntu + Docker + Vaultwarden + Tailscale 自建密码管理器

使用 Ubuntu Docker Vaultwarden Tailscale 自建密码管理器 先决条件 一台运行 Ubuntu 系统的服务器。可以是云提供商的 VPS、家庭网络中的树莓派、或者 Windows 电脑上的虚拟机等等 一个 Tailscale 账户。如果还没有 Tailscale 账户,可以通过此链接迅速创建一个…

基于Udp(收发信息使用同一个socket)网络通信编程

想要实现网络通信那么就要有一个客户端一个服务器 客户端发送数据,服务器接收数据并返回数据 网络通信就是进程通信 所以我们用两个程序来分别编写客户端和服务器 服务器 1,设置端口号, 2、ip可以固定位127.0.0.1来用于本地测试&#xff0c…

基于文本来推荐相似酒店

基于文本来推荐相似酒店 查看数据集基本信息 import pandas as pd import numpy as np from nltk.corpus import stopwords from sklearn.metrics.pairwise import linear_kernel from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extrac…

TPshop商城的保姆教程(windows)

提前准备 phpStudy下载:https://www.xp.cn/download.html 选择适合自己的版本下载 TPshop商城源文件下载链接: https://pan.baidu.com/s/143fLrxbwe9CTMCbyx7mXJQ?pwd6666 开始安装 安装完phpstudy后 以管理员的身份启动phpstudy.exe 选择合适自己…

[猫头虎分享21天微信小程序基础入门教程] 第20天:小程序的多媒体功能与图像处理

[猫头虎分享21天微信小程序基础入门教程] 第20天:小程序的多媒体功能与图像处理 第20天:小程序的多媒体功能与图像处理 🎨 自我介绍 大家好,我是猫头虎,一名全栈软件工程师。今天我们继续微信小程序的学习&#xff…

SRE视角下的DevOps构建之道

引言: 随着数字化时代的飞速发展,软件成为了企业竞争力的核心。为了更高效地交付高质量的软件,DevOps(Development和Operations的组合)作为一种文化、实践和工具集的集合,逐渐成为了行业内的热门话题。然而…

记录贴 Elasticsearch的RestClient进行DSL查询

must:必须匹配每个子查询,类似“与” should:选择性匹配子查询,类似“或” must_not:必须不匹配,不参与算分,类似“非” filter:必须匹配,不参与算分 package com.h…

java中的工具类

以下是我们到现在学的三个类 在书写工具类的时候我们要遵循以下的规则 类名见面知意是为了知道这个工具类的作用 私有化构造方法的作用是为了不让外界不能创造这个类的对象吗,因为工具类不是描述一个事物的,它是一个工具。 方法定义位静态是为了方便调用…

网页中的音视频裁剪拼接合并

一、需求描述 项目中有一个配音需求: 1)首先,前台会拿到一个英语视频,视频的内容是A和B用英语交流; 2)然后,用户可以选择为某一个角色配音,假如选择为A配音,那么视频在播…

Linux学习笔记(二)

一、Linux文件目录 1.命令:tree -L 1 2.挂载命令(例如U盘,需要挂载之后才能访问): mount /dev/cdrom /mnt ls /mnt 3.查看登录信息: last / lastlog 4.修改/查看网络信息 vi /etc/sysconfig/netw…