线程Thread
文章目录
- 一、概念
- 1、进程
- 2、线程
- 3、CPU与线程的关系
- 4、并行、并发
- 5、线程的生命周期
- 二、创建
- 1、继承Thread
- 2、实现Runnable接口
- 3、实现Callable接口
- 三、API
- 1、获取运行使用的线程
- 2、唯一标识
- 3、线程名
- 4、优先级
- 5、是否处于活动状态
- 6、守护线程
- 7、join
- 1、API
- 2、有无join对比
- 8、yield
- 9、sleep
- 10、线程中断
一、概念
1、进程
- 进程就是正在运行中的程序
2、线程
- 是1个进程(程序内部)的1条执行路径
- 单线程:1个进程中只有1个线程(1条执行路径)
- 多线程:1个进程中包含多个线程(多条执行路径)
- 线程之间堆内存、方法区内存共享;但是栈内存独立,1个线程一个栈
3、CPU与线程的关系
- 单核CPU:不能够做到真正的多线程并发,因为在一个时间单元内,只能执行一个线程的任务,多个线程谁获取时间片运行谁,每个线程获取时间片的概率相等,可能:t1、t2、t2、t2;给人一种多线程并发的感觉:其实是由于CPU的处理速度极快,多个线程之间频繁切换执行,跟人来的感觉是多个事情同时在做
4、并行、并发
- 并行:多核CPU同时执行多个任务。比如:多个人同时做不同的事
- 并发:单核CPU同时执行多个任务。比如:多个人做同一件事
5、线程的生命周期
- 新建状态
- 新建了线程对象,还没调用start方法
- 就绪状态
- 线程调用了start方法等待获取CPU时间片
- 表示当前线程具有抢夺CPU时间片的权力
- 运行状态
- 线程对象开始执行run方法
- run方法的开始执行标志着这个线程进入运行状态,当之前占有的CPU时间片用完之后,会重新回到就绪状态继续抢夺CPU时间片,当再次抢到CPU时间之后,会重新进入run方法接着上一次的代码继续往下执行
- 阻塞状态
- 当一个线程遇到阻塞事件,例如:sleep方法、获取synchronized排他锁失败(因为锁被其它线程所占用)等,此时线程会进入阻塞状态,阻塞状态的线程会放弃之前占有的CPU时间片,之前的时间片没了需要再次回到就绪状态抢夺CPU时间片
- 死亡状态
- run方法执行完毕或者因异常退出了run方法,该线程生命周期结束
二、创建
1、继承Thread
class Thread implements Runnable- 缺点:
- 由于java是单继承的,这导致继承了Thread后就不能在继承其它类了;在实际开发中会经常继承某个超类来复用其中的方法,这导致两者不能同时继承
- 继承线程后重写run方法来定义任务,这又导致我们将任务直接定义在线程上使得线程只能做该任务,无法并发执行其他任务,重用性变差
public class HandleMsg extends Thread{/** 线程标识 */private String threadKey;/** 构造方法用来区分不同线程便于测试 */public HandleMsg(String threadKey){this.threadKey=threadKey;}@Overridepublic void run(){for(int i=0;i<10;i++){System.err.println(threadKey+":run");}}}//匿名内部类lambda
Thread t1=new Thread(()->{for(int i=0;i<10;i++) {System.err.println("t1:run");}
};//创建2个线程对象
HandleMsg h1=new HandleMsg("h1");
HandleMsg h2=new HandleMsg("h2");//启动线程,开始执行实现的run方法
h1.start();
h2.start();
2、实现Runnable接口
- 优点:线程和线程执行的任务分离
public class HandleMsg implements Runnable{/** 线程标识 */private String threadKey;/** 构造方法用来区分不同线程便于测试 */public HandleMsg(String threadKey){this.threadKey=threadKey;}@Overridepublic void run(){for(int i=0;i<10;i++){System.err.println(threadKey+":run");}}}//创建2个任务对象
HandleMsg h1=new HandleMsg("h1");
HandleMsg h2=new HandleMsg("h2");//将任务1交给线程1
Thread t1=new Thread(h1);
//将任务2交给线程2
Thread t2=new Thread(h2);//启动线程,开始执行任务的run方法
t1.start();
t2.start();
3、实现Callable接口
FutureTask implements RunnableFuture,RunnableFuture<V> extends Runnable- 优点
- 线程和线程执行的任务分离
- 有返回值
- 可以声明抛出的异常
//Callable的泛型就是重写的call方法的返回值类型
public class HandleMsg implements Callable<String>{/** 线程标识 */private String threadKey;/** 构造方法用来区分不同线程便于测试 */public HandleMsg(String threadKey){this.threadKey=threadKey;}@Overridepublic String call() throws Exception{for(int i=0;i<10;i++){System.err.println(threadKey+":run");}return threadKey;}}//创建2个任务对象
HandleMsg h1=new HandleMsg("h1");
HandleMsg h2=new HandleMsg("h2");//创建FutureTask类包装任务对象,泛型就是任务类实现Callable的泛型,也就是call方法返回值的类型
FutureTask<String> f1=new FutureTask<>(h1);
FutureTask<String> f2=new FutureTask<>(h2);//将FutureTask对象交给线程
Thread t1=new Thread(f1);
Thread t2=new Thread(f2);//启动线程,开始执行任务的run方法
t1.start();
t2.start();//获取返回值
String result1=f1.get();
String result2=f2.get();
三、API
1、获取运行使用的线程
//在哪个方法执行就获取执行该方法的线程
Thread thread=Thread.currentThread();
2、唯一标识
long getId();
3、线程名
String getName();//线程启动之前可以设置线程名
void setName(String name);
4、优先级
- 线程有10个优先级,用1-10表示,默认为5
int getPriority();//启动之前设置
//线程无法主动获取cpu时间片,唯一可以干涉线程调度工作的方式就是修改线程的优先级,最大程度的改善获取cpu时间片的几率,理论上,线程优先级越高的线程获取cpu时间片的次数越多
void setPriority(int newPriority);
5、是否处于活动状态
boolean isAlive();
6、守护线程
- 守护线程又称为后台线程,默认创建出来的线程都是普通线程或称为前台线程
- 当进程结束时,所有正在运行的守护线程都会被强制中断
- 进程的结束:当一个进程中没有任何前台线程时即结束
- main主线程就是前台线程,不受其他线程影响,分配其他线程后接着干自己的事,其他线程执行的时候,main线程可能已经结束了
//是否为守护线程
boolean isDaemon();//启动之前设置
void setDaemon(boolean on);
7、join
- 作用是:让当前执行的线程陷入等待(内部调用了wait方法)。
- 永久等待:其实现原理是不停的检查当前线程是否存活,该线程的任务执行完毕后就会处于死亡状态,如果存活则说明任务还未执行完毕-继续等待
- 线程启动之后调用
1、API
//等待线程执行完任务后再往下执行,join(0);
void join();//等待线程执行一段时间后再往下执行,无论线程任务是否执行完毕,单位:毫秒
void join(long millis);
2、有无join对比
//1、程序正常运行顺序是不会等待线程任务执行完毕,就会往下执行
Thread t1=new Thread(()->{for(int i=0;i<5;i++){System.err.println(i);}
});
t1.start();System.err.println("next task");// 输出结果
// next task
// 0
// 1
// 2
// 3
// 4//2、调用join
Thread t1=new Thread(()->{for(int i=0;i<5;i++){System.err.println(i);}
});
t1.start();t1.join();System.err.println("next task");// 0
// 1
// 2
// 3
// 4
// next task
8、yield
- 线程让步
- 暂停(不是终止)当前正在执行的线程任务,让其它具有相同优先级或更高优先级的等待的线程执行任务(其它也会包含暂停的线程,所以有可能刚暂停就执行)
- 暂停的线程状态变化:运行状态 -> 就绪状态
- 暂停期间不会释放锁,所以其他线程获取不到锁
9、sleep
- 使线程睡眠
- sleep的睡眠期间不会释放锁,所以其它线程获取不到锁
- 睡眠线程的状态变化:运行状态 -> 阻塞状态 -> 就绪状态
//Thread的静态方法,单位:毫秒
static void sleep(long millis) throws InterruptedException;
- sleep和wait的区别
| sleep | wait |
|---|---|
| 属于Thread类 | 属于Object类 |
| 可以在任何地方使用 | wait、notify、notifyAll 只能在同步方法、同步控制块里面使用 |
| 睡眠期间不会释放锁 | 会释放锁,而且会将当前线程加入到等待队列中 |
| 不需要唤醒 | 可以被notify、notifyAll唤醒 |
10、线程中断
- 只是打断线程的睡眠,不会终止线程的继续执行
//线程是否中断
boolean isInterrupted();//中断线程睡眠
Thread t1=new Thread(()->{System.err.println("run......");try{//睡眠10sThread.sleep(10000L);}catch(InterruptedException e){e.printStackTrace();}System.err.println("end......");
});//启动线程
t1.start();//中断睡眠
//线程不会睡眠10s,而是被中断,抛出InterruptedException,捕获该异常后,继续执行后续的代码
t1.interrupt();System.err.println("next task");// 执行结果
// next task
// run......
// end......
相关文章:
线程Thread
文章目录 一、概念1、进程2、线程3、CPU与线程的关系4、并行、并发5、线程的生命周期 二、创建1、继承Thread2、实现Runnable接口3、实现Callable接口 三、API1、获取运行使用的线程2、唯一标识3、线程名4、优先级5、是否处于活动状态6、守护线程7、join1、API2、有无join对比 …...
如何使用CSS实现一个渐变背景效果?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现渐变背景效果⭐ 线性渐变(Linear Gradient)⭐ 径向渐变(Radial Gradient)⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订…...
初始C语言(7)——详细讲解有关初阶指针的内容
系列文章目录 第一章 “C“浒传——初识C语言(1)(更适合初学者体质哦!) 第二章 初始C语言(2)——详细认识分支语句和循环语句以及他们的易错点 第三章 初阶C语言(3)——…...
ArcGIS Pro技术应用(暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合、案例应用)
GIS是利用电子计算机及其外部设备,采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲,它是在一定的地域内,将地理空间信息和 一些与该地域地理信息相关的属性信息结合起来,达到对地理和属性信息的综合管理。GIS的…...
RISC-V公测平台发布 · 数据库在RISC-V服务器上的适配评估
前言 上一期讲到YCSB在RISC-V服务器上对MySQL进行性能测试(RISC-V公测平台发布 使用YCSB测试SG2042上的MySQL性能),在这一期文章中,我们继续深入讨论RISC-V数据库的应用。本期就继续利用HS-2平台来测试数据库软件在RISC-V服务器…...
UE5.2 LyraDemo源码阅读笔记(五)输入系统
Lyra里使用了增强输入系统,首先知道增强输入系统里的三个类型配置。 一、Input Actions (IA): 输入操作带来的变量,与玩家的输入组件绑定,回调里驱动玩家行为。 二、InputMappingContext(IMC):…...
线段树详解——影子宽度
OK,今天来讲一讲线段树~~ 线段树是什么线段树的实现线段树的时间复杂度线段树的应用线段树的节点结构其他操作和优化例题——影子宽度输入输出格式输入格式输出格式 输入输出样例输入样例输出样例 例题讲解 线段树是什么 线段树( S e g m e n t Segmen…...
使用R语言绘制折线图
写在前面 昨天我们分享了使用Python绘制折线图的教程,跟着NC学作图 | 使用python绘制折线图,考虑到很多同学基本不使用Python绘图。那么,我们也使用R语言复现此图形。 此外,在前期的教程中,我们基本没有分享过折线图的教程。因此,我们在这里也制作一期关于折线图的教程。…...
无涯教程-Perl - wantarray函数
描述 如果当前正在执行的函数的context正在寻找列表值,则此函数返回true。在标量context中返回false。 语法 以下是此函数的简单语法- wantarray返回值 如果没有context,则此函数返回undef;如果lvalue需要标量,则该函数返回0。 例 以下是显示其基本用法的示例…...
【gitkraken】gitkraken自动更新问题
GitKraken 会自动升级!一旦自动升级,你的 GitKraken 自然就不再是最后一个免费版 6.5.1 了。 在安装 GitKraken 之后,在你的安装目录(C:\Users\<用户名>\AppData\Local\gitkraken)下会有一个名为 Update.exe 的…...
《Java Web程序设计》试卷03
《Java Web程序设计》试卷03 课程编码: 301209 适用专业: 计算机应用(包括JAVA方向) 注 意 事 项 1、首先按要求在试卷标封处填写你所在的系(部)、专业、班级及学号和姓名; 2、仔细阅读各类题目的回答要求,…...
怎么查看小程序中的会员信息
商家通过查看会员信息,可以更好地了解用户,并为他们提供更个性化的服务和推荐。接下来,就将介绍如何查看会员信息。 商家在管理员后台->会员管理处,可以查看到会员列表。支持搜索会员的卡号、手机号和等级。还支持批量删除会员…...
网络安全—黑客—自学笔记
想自学网络安全(黑客技术)首先你得了解什么是网络安全!什么是黑客! 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全…...
深度解读波卡 2.0:多核、更有韧性、以应用为中心
本文基于 Polkadot 生态研究院整理,有所删节 随着波卡 1.0 的正式实现,波卡于 6 月 28 日至 29 日在哥本哈根举办了年度最重要的会议 Polkadot Decoded 2023,吸引了来自全球的行业专家、开发者和爱好者,共同探讨和分享波卡生态的…...
微服务中间件--Eureka注册中心
Eureka注册中心 a.eureka原理分析b.搭建eureka服务c.服务注册d.服务发现 a.eureka原理分析 1.每个服务启动时,将自动在eureka中注册服务信息 (每个服务每隔30秒发送一次的心跳续约,当某个服务没有发送时,eurekaServer将自动剔除该服务&#x…...
积跬步至千里 || 矩阵可视化
矩阵可视化 矩阵可以很方面地展示事物两两之间的关系,这种关系可以通过矩阵可视化的方式进行简单监控。 定义一个通用类 from matplotlib import pyplot as plt import seaborn as sns import numpy as np import pandas as pdclass matrix_monitor():def __init…...
zookeeper详细介绍
ZooKeeper是一个开源的分布式协调服务,具有以下一些关键特点: 数据模型 ZooKeeper的数据模型采用层次化的多叉树形结构,每个节点称为znode,类似于文件系统中的文件和目录。每个znode可以存储数据和控制信息。一致性保证 ZooKeeper通过ZAB协议,实现分布式环境下数据的强一致性,…...
面板市场趋势分析:价格上涨势头或将减缓 | 百能云芯
8月末,面板价格报价公布,市场研究机构TrendForce指出,电视面板今年以来已经上涨超过30%,虽然下游品牌商对于价格上涨提出了不同声音,但由于面板厂商采取了按需生产的策略,8月仍然出现了3~5%的价格上涨。Tre…...
JVM性能调优
java 如何跨平台,如何一次编译到处执行 是由于java在不同的jvm上编译,jvm在软件层面屏蔽不同操作系统在底层硬件与指令上的区别。 jvm 包括 new 的对象都是放在堆中 栈,给线程单独使用(线程私有),存储一个…...
【全链路追踪】XXL-JOB添加TraceID
文章目录 一、背景调用路径部署环境问题 二、方案三、Demo示例1、MDC2、RequestInterceptor3、HandlerInterceptor4、logback.xml 四、后续改进思路 一、背景 首先这个项目属于小型项目,由于人手以及时间限制,并未引入Skywalking等中间件来做调用链路追…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能
指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...
一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...
