线程简介

线程简介

这里先说明一下,进程和线程是不同的

  • 进程:程序的执行过程,是一个独立的运行环境,持有资源和线程,相当于一个应用程序,操作系统在分配资源时把资源分配给进程(堆和方法区是属于进程的)
  • 线程:进程中执行的一个任务,系统中最小的执行单元,同一进程有多个线程,线程共享进程的资源,CPU资源分配给线程(程序计数器和栈是属于线程的)

创建一个线程Thread时,JVM将分配一大块内存到专为线程保留的特殊区域上,用于提供运行任务时所需的一切,包括:

  • 程序计数器,指明要执行的下一个JVM字节码指令,由于线程是占有CPU执行的基本单位,CPU是用时间片轮转的方式,当前线程时间片用完之后需要让出CPU,而程序计数器就是记录该线程让出CPU时的执行地址,等到下次分配到时间片时线程就可以从本身私有的计数器中指定的地址继续执行

  • 用于支持Java代码执行的栈,包含有关线程已到达当时执行位置所调用方法的信息(调用栈帧)以及每个正在执行的方法的所有局部变量

  • 第二个则用于native code执行的栈

  • 线程本地变量的存储区域

  • 用于控制线程的状态管理变量

每当调用一个方法时,当前程序计数器被推到该线程的栈上,然后栈指针向下移动以足够来创建一个栈帧,其栈帧里存储该方法的所有局部变量,参数和返回值。所有基本类型变量都直接在栈上,虽然方法中创建对象的任何引用都位于栈帧中,但对象本身存于堆中。

创建线程的方式

  • 继承Thread类,并且重写run方法

  • 实现Runnable接口,使用带参的Thread构造器来创建Thread对象

  • 实现Callable接口使用FutureTask的方式,使用带参的Thread构造器来创建Thread对象,该方式可以获取到线程执行的返回结果

    FutureTask<Integer> futureTask = new FutureTask<>(call);
    new Thread(futureTask).start();
  • 使用线程池

调用start()方法才会调用线程,如果直接调用run()方法,和普通的方法没有区别

创建一个Thread类的实例与创建其他类不同,JVM会为一个Thread实例分配两个调用栈所需的内存空间,一个调用栈用于跟踪Java代码间的调用关系,另一个用于跟踪Java代码对本地代码(native代码)的调用关系。且一个Thread实例通常对应两个线程,一个是JVM中的线程,另一个是与JVM中的线程相对应的依赖于JVM宿主机操作系统的本地(Native)线程

实现Runnable接口比继承Thread的优势
  • 代码可被多个线程共享,适合多个相同的代码去处理同一个资源

  • 可以避免java单继承的限制

  • 增加程序的健壮性,代码和任务分离

方法介绍

  • join() 线程加入进来,要等待该线程执行完在继续执行join之后的代码,可以确保两个线程的执行顺序

    t1.start();  
    t1.join(); // 等待t1线程执行完成,再执行t2.start()
    t2.start();

    join是当前线程等待所join的线程先执行完才继续进行,如果是多个线程的话,需要在线程的run方法中调用前一个线程的join

  • yield() 暂停当前正在执行的线程,并执行其他线程,yield()方法会使当前线程让出CPU使用权,从运行状态变成就绪状态,重新争抢cpu

  • sleep() 在指定的时间内让当前正在执行的线程休眠,暂时让出指定时间的执行权,在这期间不参与CPU的调度,但是该线程所拥有的监视器资源不会让出。使用sleep(0)可以暂时释放cpu,从运行状态变成就绪状态,这样可以让其他线程获得cpu

    在hotspot中sleep(0)的作用相当于yield()

  • getState() 获取线程状态

  • wait() Object的wait()方法、notify()、notifyAll()方法必须要与synchronized(obj)一起使用,只能针对已经获取到obj锁的情况,否则会抛出”java.lang.IllegalMonitorStateException“异常。wait()方法会释放该对象的锁资源,从而进行阻塞;notify()方法会通知等待该对象资源的线程进行唤醒

  • interrupt()方法,中断线程,将中断状态设置为true,但是不一定会被中断,只有在阻塞时才会被中断而抛出InterruptedException异常

    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
          // 只有被阻塞才会抛出异常
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
      // 该方法只会设置中断标志为true,实际上并没有被中断,还是会继续执行
        interrupt0();
    }
  • isInterrupted()方法,实例方法,检查当前线程是否被中断,如果是返回true,调用该方法不会改变中断状态

  • interrupted()方法,静态方法,检查线程是否被中断,与isInterrupted()不同的是,该方法如果发现当前线程被中断,则会清除中断标志,将中断状态重置为false,且该方法是静态方法,判断的是当前调用线程的中断标志而不是调用该方法的实例对象的中断标志

sleep和wait的区别
  • sleep()是Thread的静态方法,wait()是Object的方法
  • sleep()和wait()虽然都释放CPU,但是如果线程持有对象锁资源的话,sleep()在休眠时不释放锁资源,wait()在等待时会释放锁资源
  • sleep()需要捕获异常,wait()不需要
  • sleep()可以在任意位置使用,wait()必须要在synchronized同步块内使用
  • wait()当前线程必须拥有对象的监视器

线程阻塞

  • 当执行Thread.sleep方法时,会一直阻塞指定时间,或者阻塞被另一个线程打断
  • 当线程执行wait方法时,会一直阻塞到接到通知(notify方法)或者被中断或者经过指定时间为止

上下文切换

一般情况下使用多线程的时候,使用的线程个数会大于CPU个数,但是每个CPU同一时刻只能被一个线程使用,CPU资源采用了时间片轮转的策略为每个线程分配一个时间片,当前线程的时间片到后,会处于就绪状态让出CPU,这就是上下文切换,而在上下文切换时需要保存当前线程的执行现场,当再次执行时根据保存的执行现场信息恢复执行现场

线程上下文切换的时机:

  • 当前线程的CPU时间片用完处于就绪状态时
  • 当前线程被其他线程中断时

上下文切换会带来额外的开销,包括保存和恢复线程上下文信息的开销,对线程进行调度的CPU时间开销以及CPU缓存内容失效(即CPU的L1 Cache、L2Cache等)的开销

线程状态

public enum State {
    
  // 新建的线程,且还没有调用start方法启动
  // new Thread()
    NEW,

  //运行状态,等待CPU调度,包含了两个子状态READY和RUNNING
  // READY表示处于该状态的线程可以被JVM的线程调度器进行调度而使之处于RUNNING状态
  // RUNNING表示线程已经获取了CPU,正在运行
  // 调用start方法
  // yield方法  RUNNING->READY
  // 被synchronized标记的代码,获取同步监视器
  // obj.notify()/obj.notifyAll()唤醒线程
  // obj.wait(time)、thread.join(time)等待时间耗尽
    RUNNABLE,
    
  // 阻塞  等待获取synchronized同步块的对象锁或者调用wait方法之后重新进入synchronized同步块
    BLOCKED,

  // 等待  
  // 调用Object.wait、Thread.join、LockSupport.park方法会进入等待状态
  // WAITING->RUNNABLE 需要调用notify、notifyAll或者等待调用Thread.join的终止  
    WAITING,

  // 调用Thread.sleep、Object.wait(long)、Thread.join(long)、LockSupport.parkNanos、LockSupport.parkUntil这种等待超时
    TIMED_WAITING,
  
  // 线程完成工作
  // 1.run方法执行完毕正常退出  2.没有捕获异常导致run方法意外终止
    TERMINATED;
}
线程状态变化
线程状态变化

https://zhhll.icu/2020/多线程/基础/1.线程简介/

本文由 mdnice 多平台发布

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【YOLO v5 v7 v8 v9小目标改进】辅助超推理SAHI:分而治之,解决高分辨率图像中小物体检测的问题

辅助超推理SAHI&#xff1a;分而治之&#xff0c;解决高分辨率图像中小物体检测的问题 设计思路结构小目标涨点YOLO v5 魔改YOLO v7 魔改YOLO v8 魔改YOLO v9 魔改 论文&#xff1a;https://arxiv.org/pdf/2202.06934.pdf 代码&#xff1a;https://github.com/obss/sahi 设计思…

C++内存泄漏检测

C进阶专栏&#xff1a;http://t.csdnimg.cn/aTncz 相关系列文章 C技术要点总结, 面试必备, 收藏起来慢慢看 C惯用法之RAII思想: 资源管理 C智能指针的自定义销毁器(销毁策略) 目录 1.内存泄漏概述 1.1.内存泄漏产生原因 1.2 内存泄漏导致的后果 1.3 内存泄漏解决思路 2.宏…

基于Springboot免费搭载轻量级阿里云OSS数据存储库(将本地文本、照片、视频、音频等上传云服务保存)

一、注册阿里云账户 打开https://www.aliyun.com/&#xff0c;申请阿里云账户并完成实名认证&#xff08;个人&#xff09;。这种情况就是完成了&#xff1a; 二、开通OSS服务 点击立即开通即可。 三、创建Bucket 申请id和secert&#xff1a; 进去创建一个Accesskey就会出现以…

【Qt学习】QProgressBar的使用(进度条的实现)

文章目录 1. 介绍2. 实例2.1 按钮启动进度条2.2 更改进度条样式2.3 资源文件 1. 介绍 详细的 QProgressBar 内容可以通过 查阅Qt官方文档 &#xff0c;这里进行简要的总结&#xff1a; QProgressBar 是Qt框架中的一个控件&#xff0c;用于显示进度条&#xff1a; QProgressBar…

wordpress免费主题下载

免费wordpress模板下载 简洁大气的文化艺术类wordpress模板&#xff0c;可以免费下载&#xff0c;实用易上手&#xff0c;新手也适合。 https://www.wpniu.com/themes/304.html 免费wordpress主题下载 高端大气上档次的wordpress主题&#xff0c;也可以是免费的&#xff0c;…

修改MonkeyDev默认配置适配Xcode15

上一篇文章介绍了升级Xcode15后,适配MonkeyDev的一些操作,具体操作可以查看:Xcode 15 适配 MonkeyDev。 但是每次新建项目都要去修改那些配置,浪费时间和精力,这篇文章主要介绍如何修改MonkeyDev的默认配置,做到一次修改永久生效。 MonkeyDev的默认安装路径是在/opt/Mo…

iclone更奇怪了用自动对齐才搞得定

1前一个clip的位置 2选root的话就跑到这里了&#xff0c;跟前一个clip差很多 3换了left foot对齐之后才正常 4这时候开不开自动对齐不影响 5奇怪医生的中心似乎是途中的花坐标轴偏离人体好多呀不知何时跑这里的难道前面是应为这个&#xff1f;中心跑了我还不知道 6动画交叉的时…

【常见索引使用】⭐️Mysql中索引的类型以及使用方式和失效场景

目录 一、前言 二、数据准备 三、索引的分类 四、索引示例 示例1、主键索引&#xff08;Primary Key Index&#xff09;与 唯一索引&#xff08;Unique Index&#xff09; 示例2、前缀索引&#xff08;Prefix Index&#xff09; 示例3、联合索引&#xff08;复合索引&am…

GWO-RF|灰狼算法优化随机森林 分类预测|多变量分类预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、算法介绍&#xff1a; 灰狼优化算法&#xff1a; 随机森林&#xff1a; 四、完整程序下载&#xff1a; 一、程序及算法内容介绍&#xff1a; …

如何规划应用商店优化策略

应用商店是拥挤的地方。拥有超过 600 万个应用程序&#xff0c;制定应用程序商店优化 (ASO) 策略比以往任何时候都更加重要。ASO 有助于确保您的应用在搜索结果中排名更高&#xff0c;以便潜在用户可以轻松找到它。通过针对App Store和 Google Play优化App&#xff0c;能够吸引…

使用ES检索PDF或Word等格式文件方案

#大数据/ES #经验 #方案架构 ES检索PDF/Word等格式文件方案 插件安装 ES有文档预处理插件&#xff0c;但是7.x版本默认发版包不包含这个ingest attachment plugin 。 通过摄取附件插件&#xff0c;Elasticsearch 可以使用 Apache 文本提取库 Tika 提取常见格式的文件附件&a…

Tomcat介绍在IDEA中创建JavaWeb工程

文章目录 一、WEB服务器服务器概述使用Java代码手写web服务器 二、服务器软件Web服务器服务器软件的使用步骤 三、TomcatTomcat的下载Tomcat的安装与卸载Tomcat的启动与关闭常见问题 四、新建Java Web项目并将项目部署到tomcat中新建Java Web项目将项目部署到Tomcat中出现的问题…

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)--大模型

专属领域论文订阅 VX关注{晓理紫}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 如果你感觉对你有所帮助&#xff0c;请关注我&#xff0c;每日准时为你推送最新论文。 》》 由于精力有限&#xff0c;今后就不在CSDN上更…

去除PDF论文行号的完美解决方案

去除PDF论文行号的完美解决方案 1. 遇到的问题 我想去除论文的行号&#xff0c;但是使用网上的Adobe Acrobat裁剪保存后 如何去掉pdf的行编号&#xff1f; - 知乎 (zhihu.com) 翻译时依然会出现行号&#xff0c;或者是转成word&#xff0c;这样就大大损失了格式&#xff0c;…

第十五届蓝桥杯青少组STEMA测评SPIKE初级真题试卷 2024年1月

第十五届蓝桥杯青少组STEMA测评SPIKE初级真题试卷 2024年1月 ​​​​​​​ 来自&#xff1a;6547网 http://www.6547.cn/doc/vywur8eics

SOC设计:关于时钟门控的细节

有如下几个信号 输入信号 1、同步后的rstnsync_clk 2、时钟&#xff1a;clk 3、test_mode 4、软件控制信号&#xff1a;clk_sub_en 输出信号 1、clk_sub 功能&#xff1a;软件配置的使能信号clk_sub_en经过时钟clk 2拍同步处理后产生clk 域下的enable信号&#xff0c;然…

常用MII接口详解

开放式系统互连 (OSI) 模型 七层开放系统互连 (OSI) 模型中&#xff0c;以太网层 位于最底部两层 - 物理层和数据链路层。 从百兆以太网接口开始 首先是百兆以太网规定的两种接口 介质无关接口 (MII) Media Independent Interface 介质相关接口 (MDI) Medium Depen…

深入探讨javascript的流程控制与分支结构,以及js的函数

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属的专栏&#xff1a;前端泛海 景天的主页&#xff1a;景天科技苑 文章目录 1.流程控制与分支结构1.if分支结构2.switch case 分支结构3.循环结…

九型人格测试,7号活跃型人格的职业分析

九型人格中的7号人格&#xff0c;也叫活跃型人格&#xff0c;正如名字所形容的那样&#xff0c;一个活跃型人格的人&#xff0c;会让你体会到生活的乐趣。跟他们在一起的时候&#xff0c;永远不会感到无聊&#xff0c;即便是在停电的下午&#xff0c;也能在屋子里愉快的折腾。活…

【RK3288 Android6, T8PRO 快捷按键 gpio 配置上拉输入】

文章目录 【RK3288 Android6&#xff0c; T8PRO 快捷按键 gpio 配置上拉输入】需求开发过程尝试找到没有用的上拉gpio尝试修改pwm1的gpio的默认上拉模式 改动 【RK3288 Android6&#xff0c; T8PRO 快捷按键 gpio 配置上拉输入】 需求 T8pro想要模仿T10 的 快捷按键&#xff…