并发编程1:线程的基本概念

一、进程、线程、用户线程&原生线程、优先级、守护线程

什么是进程

  • 是程序一次执行的过程,是系统运行程序的基本单位。
  • 系统运行一次程序,就是一个进程从创建到关闭的过程。
  • Java 项目从 main 方法启动,就是启动了一个 JVM 进程,而 main 函数就是由进程中的一个线程负责执行,这个线程称为主线程。

什么是线程

  • 线程和进程相似,但是是一个比线程更小的单位,线程间的切换比进程的切换负担小得多,所以线程也称为轻量级进程。
  • 一个进程执行时可以有多个线程,JAVA 线程之间可以共享堆和方法区资源,但是每个线程有自己的程序计数器、虚拟机栈、和本地方法栈

什么是用户线程&原生线程

  • 用户线程:JDK1.2 之前 JVM 使用的是绿色线程自己摸你的多线程,这就是用户线程。用户线程对比原生线程使用起来有一些限制。用户线程由用户空间程序管理和调度,运行在用户空间。JDK1.2 之后,JAVA 线程,就是用的是内核线程了。
  • 内核线程:由操作系统内核管理和调度的线程,运行在内核空间,可以操作系统提供的异步 I/O

什么是守护线程&非守护线程

  • JAVA 中可以在线程 start 前使用 setDaemon() 方法指定其为守护线程,守护线程和非守护线程最大的区别在于他们如何影响程序的结束。
  • 非守护线程执行完毕时,程序就会结束执行。不论是否有守护线程仍在执行。

线程优先级

可以对线程设置优先级,默认优先级为 Thread.NORM_PRIORITY(5),优先级从 1~10 优先级越大优先执行的概率越高但并不能保证执行顺序。

多线程和上下文切换

  • 线程在执行过程中,会有自己的运行条件和状态这就是线程的上下文。例如 Java 线程私有的程序计数器,虚拟机栈、本地方法栈。
  • 线程在执行过程中可能出现阻塞、等待、或者 CPU 时间片执行完毕,的情况要让出 CPU 等待下一次执行。这种情况下就会发生线程切换,下一次执行时又要恢复线程的数据,这就是上下文切换
  • 因为需要上下文切换,如果是 CPU 密集型任务,线程越多反而有更多的性能损耗;

二、线程的状态和切换

JAVA 的线程状态定义在 Thread.States枚举类中

  • NEW:Thread对象已经创建,但是还没有开始执行。
  • RUNNABLE:Thread对象正在Java虚拟机中运行。
  • BLOCKED : Thread对象正在等待锁定。
  • WAITING:Thread 对象正在等待另一个线程的动作。
  • TIME_WAITING:Thread对象正在等待另一个线程的操作,但是有时间限制。
  • TERMINATED:Thread对象已经完成了执行。

Java 的线程状态没有区分 操作系统层面的 Running 和 Ready 状态,而是只有 RUNNABLE 状态的原因

  • 因为 现在的 CPU 都讲 CPU 资源进行分片循环调度,由于时间片非常小一般是 10~20ms,线程切换的非常快所以区分 Ready 和 Running 意义不大

线程的终止方式

  1. 调用 stop 方法强行终止,但是是强行终止线程可能任意时刻被中指导致任务不完整,资源未释放等问题。
  2. 线程中保存 volite 的退出标识,线程中循环判断该标识,是否需要终止线程,和 interrupt 很类似。
  3. 使用线程的中断标识,interrupt,可以通过isInterrupted()和 interrupted() 来感知外界传入的中断状态,决定是否中断线程。interrupt 碰上 sleep 或者 wait 状态 则一定会抛出异常
class Task implements Runnable {@Overridepublic void run() {try {while (!Thread.currentThread().isInterrupted()) {System.out.println("子线程正在运行...");Thread.sleep(1000); // 让子线程休眠1秒}} catch (InterruptedException e) {System.out.println("子线程被中断");} finally {System.out.println("子线程结束");}}
}

三、线程的创建 Runnable 接口 和 Thread 类

线程可以直接集成 Thread 类,也可以实现 Runnable 接口将 Runnable 对象作为参数创建 Thread

Runnable 接口

  • Runnable 接口只有一个 run 方法,用来记录线程需要执行的任务内容

Thread 类

  • 获取和设置 Thread 对象信息
    • getId():该方法返回Thread对象的标识符。该标识符是在钱程创建时分配的一个正整数。在线程的整个生命周期中是唯一且无法改变的。
    • getName()/setName():这两种方法允许你获取或设置Thread对象的名称。这个名称是一个String对象,也可以在Thread类的构造函数中建立
    • getPriority()/setPriority():你可以使用这两种方法来获取或设置Thread对象的优先级。
    • isDaemon()/setDaemon():这两种方法允许你获取或建立Thread对象的守护条件
    • getState():该方法返回Thread对象的状态。
  • interrupt():中断目标线程,给目标线程发送一个中断信号,线程被打上中断标记。
  • interrupted():判断目标线程是否被中断,但是将清除线程的中断标记。
  • **isinterrupted():**判断目标线程是否被中断,不会清除中断标记。
  • **sleep(long ms):**该方法将线程的执行暂停ms时间。
  • **join():**暂停线程的执行,直到调用该方法的线程执行结束为止。可以使用该方法等待另一个Thread对象结束。举例 : A 线程中执行 b.join() 则执行流程为 A->暂停->b 开始执行->b 执行完毕->A 继续
  • setUncaughtExceptionHandler() 当线程执行出现未校验异常时,该方法用于建立未校验异常的控制器。
  • currentThread():Thread类的静态方法,返回实际执行该代码的Thread对象。
  • suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。典型地,suspend() 和 resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个线程产生了结果后,调用 resume() 使其恢复。
  • yield() 方法使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程。

Callable 接口和 Runnable 接口

Callable 接口是一个和 Runnable 接口非常相似的接口

  • Callable 接口内部是带有返回值的 call()方法,而 Runnable 接口是没有返回值的 run()方法。
  • Callable 接口一般配合 Future 来一起使用,使用 Future 来包装 Callable 对象,实现 callable 的异步执行和后续的结果获取。

public static void main(String[] args) throws ExecutionException, InterruptedException {MyCallable myCallable = new MyCallable();//future接口不能被异步执行,FutureTask实现了RunnableFuture接口,间接实现了Runnable接口FutureTask<String> stringFuture = new FutureTask<String>(myCallable);//使用Thread执行或者提交给线程池执行Thread thread = new Thread(stringFuture);System.out.println("外部调用任务开始" + new Date());thread.start();//这里阻塞获取结果,如果出结果了可以直接获取,否则需要等待任务执行完毕System.out.println("获取结果:" + stringFuture.get());}/**
* 这是自定义的future类
*
* @author liuyp
* @date 2023/11/19
*/
static class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {System.out.println("任务执行开始,预计耗时5s");Thread.sleep(5000);return "我是任务执行的结果";}
}

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

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

相关文章

JS中闭包

相信JS的开发者&#xff0c;对闭包这个知识都比较熟悉&#xff0c;在熟悉的同时可能会有些模糊的不真切感&#xff0c;下面咱们从三个方面来具体加深一下对闭包的理解。 什么是闭包 咱们先看两个比较抽象的理解&#xff0c;闭包是一个函数和其关联环境组成的结构体&#xff1b…

C++面试宝典第1题:爬楼梯

题目 小乐爬楼梯&#xff0c;一次只能上1级或者2级台阶。楼梯一共有n级台阶&#xff0c;请问总共有多少种方法可以爬上楼&#xff1f; 解析 这道题虽然是一道编程题&#xff0c;但实际上更是一道数学题&#xff0c;着重考察应聘者的逻辑思维能力和分析解决问题的能力。 当楼梯只…

理解Zookeper

一、什么是Zookeper Zookeper是一个可以作为注册中心、配置中心、分布式锁的分布式解决方案 二、数据一致性 一致性分为强一致性、弱一致性、最终一致性 Zookeper可以保持数据的强一致性&#xff08;CP&#xff09; 主要是解决写、集群节点的同步、读之间的关系 强一致性&a…

nodejs微信小程序+python+PHP问卷调查系统的设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

This详细用法

this的指向 this有5种指向&#xff0c;在普通函数中&#xff0c;this指向window&#xff1b;在构造函数中&#xff0c;this指向创建的对象&#xff1b;在方法声明中&#xff0c;this指向调用者&#xff1b;在定时器中&#xff0c; this指向window&#xff1b;在事件中&#xff…

超大规模集成电路设计----MOS器件原理(二)

本文仅供学习&#xff0c;不作任何商业用途&#xff0c;严禁转载。绝大部分资料来自----数字集成电路——电路、系统与设计(第二版)及中国科学院段成华教授PPT 超大规模集成电路设计----MOS器件原理&#xff08;二&#xff09; 半导体物理知识补充介绍1. 半导体材料2. 固体类型…

如何做性能优化?

性能优化是一个复杂的过程&#xff0c;它涉及到对软件或网站的结构、代码、数据库和硬件的深入理解和改进。以下是一些通用的性能优化建议&#xff1a; 代码优化&#xff1a; 减少数据库查询&#xff1a;尽量避免N1查询问题&#xff0c;使用索引优化&#xff0c;或者考虑使用内…

如何查看JDK动态代理自动生成的类

JDK提供了一种强大且灵活的机制,可以在运行时生成代理类。这种动态生成的代理类可以在不修改原始类的情况下,对其方法进行拦截和增强。然而,对于初学者来说,了解生成的代理类的内部结构和工作原理可能会很有帮助。 本文将介绍如何查看JDK动态代理生成的代理类。我们将探索一…

RK3568平台开发系列讲解(Linux系统篇)通过OF函数获取属性

🚀返回专栏总目录 沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍通过OF函数获取属性。 一、获取获取属性 ① of_find_property 函数 of_find_property 函数用于在设备树中查找节点 下具有指定名称的属性。 如果找到了该属性, 可以通过返回的属性结构体…

Shell循环:expect(二)

expect实战&#xff1a;公钥推送 一、准备工作&#xff1a;安装expect&#xff0c;装备公钥 二、通过shell循环判断主机在线 #!/bin/bash #脚本编写 #创建一个IP地址文件 >ip.txt #使用for循环ping测试主机是否在线 for i in {3..254} do{ip192.168.151.$iping -c1 -W…

【重点】【滑动窗口】438. 找到字符串中所有字母异位词

题目 1.自己想的垃圾方法 class Solution {public List<Integer> findAnagrams(String s, String p) {List<Integer> res new ArrayList<>();char[] sArray s.toCharArray();char[] pArray p.toCharArray();Arrays.sort(pArray);String pSorted String…

29 kafka动态配置

为什么需要动态配置 线上运行的kafka broker修改配置需要重启的话&#xff0c;影响比较大。需要一个不需要重启就能使参数生效的功能 使用的场景 配置优先级&#xff1a; per-broker参数 > cluster-wide参数 > static参数 > 默认参数 1.动态调整network线程数和工…

tomcat PUT任意方法写文件

漏洞介绍 该漏洞是Apache Tomcat服务器中的PUT方法任意写文件漏洞,可以让攻击者上传Webshell并获取服务器权限。 该漏洞在2017年9月19日被Apache官方发布并修复CVE-2017-12615。在conf/web.xml文件中,readonly默认为true,当设置为false时,可以通过PUT / DELETE进行文件操作…

【C++练级之路】【Lv.2】类和对象(上)(类的定义,访问限定符,类的作用域,类的实例化,类的对象大小,this指针)

目录 一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装4.1 访问限定符4.2 封装 五、类的作用域六、类的实例化七、类的对象大小的计算7.1 类对象的存储方式猜测7.2 如何计算类对象的大小 八、类成员函数的this指针8.1 this指针的引出8.2 this指…

【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐

文章目录 题单来源经典题单496. 下一个更大元素 I&#xff08;单调栈模板题&#xff09;503. 下一个更大元素 II&#xff08;单调栈循环数组&#xff09;2454. 下一个更大元素 IV&#xff08;第二个更大的元素&#xff1a;两个单调栈&#xff09;456. 132 模式&#xff08;单调…

操作系统||经典进程同步问题之读者-写者问题

一个数据文件或记录可被多个进程共享 【问题描述】 有读者和写者两组并发进程&#xff0c;共享一个文件&#xff0c;当两个或两个以上的读进程同时访问共享数据时不会产生副作用&#xff0c;但若有某个写进程和其他进程&#xff08;读进程或写进程&#xff09;同时访问共享数…

Autosar COM通信PDU

文章目录 Autosar 中各个PDU所在示意图PDU的分类PDU 和 SDU 的关系I-PDUN-PDUL-PDU相关协议其他参考 Autosar 中各个PDU所在示意图 PDU的分类 在Autosar 中&#xff0c;主要有 I-PDU、N-PDU和 L-PDU 三种。 L-PDU&#xff1a;Data Link Layer PDU&#xff0c;数据链路层PDUN-…

react(2) - react-redux的基本使用

react-redux的基本使用 基本使用 1、下载react-redux和redux yarn add react-redux redux 2、创建Store 按照上一篇文章中redux的基本使用创建redux有关的四个文件。 3、引入Store 在index.js中&#xff0c;从react-redux中引入Provider组件&#xff0c;包裹根组件&#xff…

[C/C++]数据结构 关于二叉树的OJ题(利用分治思想解决难题)

题目一: 单值二叉树 &#x1f6a9;⛲&#x1f31f;⚡&#x1f966;&#x1f4ac; &#x1f6a9;题目链接:力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 ⛲题目描述: 如果二叉树每个节点都具有相同的值&#xff0c;那么该二叉树就是单值二叉树。…

制作飞腾(arm)芯片架构的nexus镜像

nexus官方没有arm架构的镜像&#xff0c;下面介绍一种自己制作镜像的方式 1、事先准备 在一个arm架构机器上安装docker下载nexus的linux版(https://www.sonatype.com/download-oss-sonatype)下载centos的arm架构镜像(docker pull centos-centos8.4.2105)下载arm版本的java8(ht…