当前位置: 首页 > news >正文

Java多线程基础

文章目录

  • Java多线程基础
    • 一、什么是进程与线程?
    • 二、线程和进程的区别【重点】
    • 三、线程的创建方式【重点】
      • 1. 继承Thread类
      • 2. 实现Runnable接口
      • 3. lambda 表达式
    • 四、Thread的常见属性
      • 线程中断
        • 自己定义一个标志位
        • Thread类提供的静态方法
      • 线程的状态

Java多线程基础

一、什么是进程与线程?

进程

当我们双击运行电脑程序的时候,操作系统就会为其创建一个进程,这个进程就是来维护这个程序在电脑内存上运行的状态(从双击运行到点击关闭期间)线程是操作系统分配资源的基本单位

为什么要有进程

进程的出现就是因为我们的单核CPU发展到了瓶颈了,这时就出现了多核CPU,而进程也是为了更加充分的利用多核CPU的资源**(并行+并发)**,但是每个进程的创建与销毁,消耗了太多的资源,所以就以进程为基础,剥离出来了线程的概念

并行与并发

并行:一个CPU以时间片轮转的方式依次执行每个线程,某一段时间宏观来看,就像是多个线程一同执行一样

并发:多个线程在同一个时间点同时运行

线程

线程是从进程中剥离出来的,因此,一个进程是可以剥离出多个线程的,而进程是操作系统分配资源的基本单位,所以这多个线程就会公用该进程的资源,因此线程的创建与销毁是比进程的消耗更小了,从而提升了并发编程的效率

虽然线程相对于进程的消耗已经减少了许多,可是在有的场景下,就是需要频繁创建与销毁线程,这时线程的消耗也起来了,所以 Java 进入了 线程池的概念

线程是操作系统随机调度的基本单位

主要应用场景

  1. 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
  2. I/O 密集型,多线程可以充分利用CPU,在执行IO操作的时候(需要等待),让线程去干点别的事情

二、线程和进程的区别【重点】

  1. 进程包含线程,线程是在进程内部的
  2. 每个进程都有自己独立的虚拟地址空间,也有自己独立的文件描述符表;同一个进程的多个线程之间,则共用这一份虚拟地址空间和文件描述符表
  3. 进程是操作系统中资源分配的基本单位。线程是操作系统中调度执行的基本单位
  4. 多个进程同时运行时,如果一个进程挂了,一般不会影响别的进程;而同一个进程里面的多个线程之间,如果一个线程挂了,很可能把整个进程带走了,当前进程的其他线程也就没了

三、线程的创建方式【重点】

1. 继承Thread类

class MyThread extends Thread {@Overridepublic void run() {while (true) {System.out.println("Hello thread");}}
}public class Demo1 {public static void main(String[] args) {Thread thread = new MyThread();thread.start();while (true) {System.out.println("Hello main");}}// 直接匿名内部类也可以public static void main(String[] args) {Thread thread = new Thread(){@Overridepublic void run() {System.out.println("hello thread");}};thread.start();System.out.println("hello main");}
}

2. 实现Runnable接口

class MyRunable implements Runnable {@Overridepublic void run() {System.out.println("hello thread");}
}public class Demo2 {public static void main(String[] args) {Thread thread = new Thread(new MyRunable());thread.start();System.out.println("hello main");}
}

3. lambda 表达式

public static void main(String[] args) {Thread thread = new Thread(()->{System.out.println("hello thread");});thread.start();System.out.println("hello main");}

四、Thread的常见属性

属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否有后台线程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()

👁‍🗨️说明:

ID:是线程的唯一标识,多个线程不能重复 (这里能获取的就是JVM中的ID标识,而操作系统内部也有一个ID)
名称:是线程的名称(方便程序员调试的时候查看)
状态:表示线程所处的情况(JVM中的状态,一共6种,往下看)
优先级:理论来说,优先级高的线程优先被调度到(它是一个数值来表示的,数值越小,优先级越高)
后台线程:JVM会在一个进程的所有非后台线程结束后,才会结束运行
是否存活:简单理解为run方法是否运行结束
线程中断:是否要提前截至 run 方法

线程中断

两种中断机制:1. 自己定义一个 flag 标志位,来控制;2. Thread提供的一个静态方法

自己定义一个标志位

// 自定义标志位来控制线程是否结束
public class Demo7 {// 用一个布尔变量表示线程是否要结束private static boolean isQuit = false;public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while (!isQuit) {System.out.println("线程运行中……");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("线程执行结束");});t.start();// 5秒钟后,中断线程Thread.sleep(5000);isQuit = true;}
}

Thread类提供的静态方法

调用 interrupt() 来实现中断,会产生两种情况:

  1. 若当前线程处于非堵塞状态,那么程序就会修改内置的标志位
  2. 若当前线程处于堵塞状态,inerrupt()的调用就会让线程中的sleep抛异常,然后被catch捕获,然后我们自己决定退不退出
public class Demo8 {public static void main(String[] args) {Thread t = new Thread(() -> {// Thread.currentThread() 获取当前线程的引用while (!Thread.currentThread().isInterrupted()) {System.out.println("线程运行中");try {Thread.sleep(1000);} catch (InterruptedException e) {
//                    e.printStackTrace();// [1] 立即退出
//                    break;// [2] 稍后退出try {Thread.sleep(1000);} catch (InterruptedException ex) {
//                        ex.printStackTrace();// 处理退出前的任务break;}}}System.out.println("线程结束");});t.start();// 调用 interrupt() 会产生两种效果:// 1. 若当前线程处于非堵塞状态,那么程序就会修改内置的标志位// 2. 若当前线程处于堵塞状态,interrupt()的调用就会让线程中的sleep抛异常,然后被catch捕获,然后我们自己决定退不退出t.interrupt();}
}

线程的状态

image-20230310162714705

  1. NEW:线程创建好了,但是还未执行 start 方法,也就是还没把该线程加到 PCB 队列中,参与调度
  2. TERMINATED:run 方法体执行完毕,但是程序还没结束(thread 变量还未销毁)
  3. RUNNABLE:调用了 start 方法后的状态,可能在 CPU上运行,也可能在就绪队列中等待调度上CPU
  4. BLOCKED:当前线程在等待锁,导致阻塞
  5. WAITING:当前线程在等待唤醒,导致阻塞(wait 操作)
  6. TIMED_WARNING:当前线程在一定时间内阻塞(sleep,join操作)

相关文章:

Java多线程基础

文章目录Java多线程基础一、什么是进程与线程?二、线程和进程的区别【重点】三、线程的创建方式【重点】1. 继承Thread类2. 实现Runnable接口3. lambda 表达式四、Thread的常见属性线程中断自己定义一个标志位Thread类提供的静态方法线程的状态Java多线程基础 一、…...

爆品分析第5期 | 一条视频带货3700+,这款斋月不锈钢厨具套装火了!

俗话说民以食为天,吃在任何一种文化中都占据重要的位置,要做出一道美味佳肴,除了食材、烹饪者的自身厨艺之外,还少不了一口好锅。新冠疫情以来,全世界范围内的封闭让很多人养成了居家做饭的习惯,不仅为厨具…...

团队管理的七个要点

要掌握团队管理的要点和做好团队管理工作,不是一件容易的事,但也远非想象中那么难。首先,我个人比较推荐所有团队管理者都能阅读下《经理人参阅:团队管理》(注意该书仅可其官网获得)这本佳作。相信会为你带…...

Go语言容器之map、list和nil

一、map map和C中map一样,里面存放的是key-value键值对在Go中map是引用类型,声明语法:var map变量名 map[key的类型]value的类型package mainimport "fmt"func main() {var mp map[string]intmpls : map[string]int{"one&quo…...

软件测试的案例分析 - 闰年1

(这是关于博客质量分的测试 https://www.csdn.net/qc) 我们谈了不少测试的名词, 软件是人写的, 测试计划和测试用例也是人写的, 人总会犯错误。错误发生之后, 总有人问: 为什么这个bug 没有测出来啊?! 我们看看一类简单的bug是如何发生的,以及如何预防…...

【强化学习】强化学习数学基础:值函数近似

值函数近似Value Function ApproximationMotivating examples: curve fittingAlgorithm for state value estimationObjective functionOptimization algorithmsSelection of function approximatorsIllustrative examplesSummary of the storyTheoretical analysisSarsa with …...

JVM系列——Java与线程,介绍线程原理和操作系统的关系

并发不一定要依赖多线程(如PHP中很常见的多进程并发)。 但是在Java里面谈论并发,基本上都与线程脱不开关系。因此我们讲一下从Java线程在虚拟机中的实现。 线程的实现 线程是比进程更轻量级的调度执行单位。 线程的引入,可以把一个进程的资源分配和执行调…...

C++打开文件夹对话框之BROWSEINFO

头文件 #include <shlobj.h> #include <windows.h> #include <stdio.h> using namespace std; 案例 string chooseFile(void) {//用户选择的路径&#xff0c;可以是TCHAR szBuffer[MAX_PATH] {0};然后再使用TCHAR 转char字符串&#xff0c;此处可以直接使…...

Nuxt项目配置、目录结构说明-实战教程基础-Day02

Nuxt项目配置、目录结构说明-实战教程基础-Day02一、Nuxt项目结构1.1资源目录1.2 组件目录1.3 布局目录1.4 中间件目录1.5 页面目录1.6 插件目录1.7 静态文件目录1.8 Store 目录1.9 nuxt.config.js 文件1.10 package.json 文件其他&#xff1a;别名二、项目配置2.1 build2.2 cs…...

单链表的头插,尾插,头删,尾删等操作

前言顺序表要求是具有连续的物理空间&#xff0c;并且数据的话是在这些空间当中是连续的存储。但这样会带来很多问题&#xff0c;比如说在头部或者说中间插入的话&#xff0c;效率不是很高&#xff1b;并且申请空间可能需要扩容&#xff0c;并且越往后一般来说都是异地扩容&…...

Qt扫盲-QProcess理论总结

QProcess理论使用总结一、概述二、使用三、通过 Channel 通道通信四、同步进程API五、注意事项1. 平台特性2. 不能实时读取一、概述 QProcess 其实更多的是与外面进程进行交互的一个工具类&#xff0c;通过这个类来启动外部进程&#xff0c;获取这个进程的标准输出&#xff0c…...

JAVA进阶 —— Steam流

目录 一、 引言 二、 Stream流概述 三、Stream流的使用步骤 1. 获取Stream流 1.1 单列集合 1.2 双列集合 1.3 数组 1.4 零散数据 2. Stream流的中间方法 3. Stream流的终结方法 四、 练习 1. 数据过滤 2. 数据操作 - 按年龄筛选 3. 数据操作 - 演员信息要求…...

Ubuntu Protobuf 安装(测试有效)

安装流程 下载软件 下载自己要安装的版本&#xff1a;https://github.com/protocolbuffers/protobuf 下载源码编译&#xff1a; 系统环境&#xff1a;Ubuntu16&#xff08;其它版本亦可&#xff09;&#xff0c;Protobuf-3.6.1 编译源码 cd protobuf# 当使用 git clone 下来的…...

驱动程序开发:FTP服务器和OpenSSH的移植与搭建、以及一些笔记

目录一、FTP服务器移植与搭建1、在ubuntu下安装vsftpd2、在window下安装FileZilla3、移植vsftpd到开发板上4、Filezilla 连接测试5、注意点二、开发板 OpenSSH 移植与使用1、移植 zlib 库2、移植 openssl 库3、移植 openssh 库4、openssh 使用测试三、关于u-boot上的操作及根文…...

优化改进YOLOv5算法之添加GIoU、DIoU、CIoU、EIoU、Wise-IoU模块(超详细)

目录 1、IoU 1.1 什么是IOU 1.2 IOU代码 2、GIOU 2.1 为什么提出GIOU 2.2 GIoU代码 3 DIoU 3.1 为什么提出DIOU 3.2 DIOU代码 4 CIOU 4.1 为什么提出CIOU 4.2 CIOU代码 5 EIOU 5.1 为什么提出EIOU 5.2 EIOU代码 6 Wise-IoU 7 YOLOv5中添加GIoU、DIoU、CIoU、…...

windows电脑pc如何使用svn获取文档和代码

一、安装svn 下载链接 也可通过其他方式下载 二、使用 2.1 随便找一个文件夹 2.2 点击右键&#xff0c;选择SVN Checkout 2.3输入网址 如当你在网页上访问时地址为https://10.197.78.78/!/#aaa/view/head/bbb 在这里不能直接填入&#xff0c;而是 https://10.197.78.78/sv…...

ROS1学习笔记:tf坐标系广播与监听的编程实现(ubuntu20.04)

参考B站古月居ROS入门21讲&#xff1a;tf坐标系广播与监听的编程实现 基于VMware Ubuntu 20.04 Noetic版本的环境 文章目录一、创建功能包二、创建代码2.1 以C为例2.1.1 配置代码编译规则2.1.2 编译整个工作空间2.1.2 配置环境变量2.1.4 执行代码2.2 以Python为例2.2.1 配置代码…...

​力扣解法汇总1590. 使数组和能被 P 整除

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣 描述&#xff1a; 给你一个正整数数组 nums&#xff0c;请你移除 最短 子数组&#xff08;可以为 …...

Spring源码阅读(基础)

第一章&#xff1a;bean的元数据 1.bean的注入方式&#xff1a; 1.1 xml文件 1.2 注解 Component&#xff08;自己写的类才能在上面加这些注解&#xff09; 1.3配置类&#xff1a; Configuration 注入第三方数据源之类 1.4 import注解 &#xff08;引用了Myselector类下…...

服务搭建篇(九) 使用GitLab+Jenkins搭建CI\CD执行环境 (上) 基础环境搭建

1.前言 每当我们程序员开发在本地完成开发之后 , 都要部署到正式环境去使用 , 在一些传统的运维体系中 , 开发与运维都是割裂的 , 开发人员不允许操作正式服务器 , 服务器只能通过运维团队来操作 , 这样可以极大的提高服务器的安全性 , 不经过安全保护的开放服务器 , 对于黑客…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...