【多线程】Thread类的用法
文章目录
- 1. Thread类的创建
- 1.1 自己创建类继承Thread类
- 1.2 实现Runnable接口
- 1.3 使用匿名内部类创建Thread子类对象
- 1.4 使用匿名内部类创建Runnable子类对象
- 1.5 使用lambda创建
- 2. Thread常见的构造方法
- 2.1 Thread()
- 2.2 Thread(Runnable target)
- 2.3 Thread(String name)
- 2.4 Thread(Runnable target, String name)
- 3. Thread常见的属性
- 4. 线程的使用
- 4.1 启动线程
- 4.2 中断线程
- 4.3 等待线程
- 4.4 休眠线程
1. Thread类的创建
1.1 自己创建类继承Thread类
package Thread;//继承Thread类实现线程
class MyThread extends Thread{@Overridepublic void run() {System.out.println("hello run");}
}
public class Dome1 {public static void main(String[] args){//创建线程MyThread myThread = new MyThread();//启动线程myThread.start();}
}
1.2 实现Runnable接口
//使用Runnable的方式创建线程
class MyRunnable implements Runnable{@Overridepublic void run() {System.out.println("hello run");}
}
public class Dome2 {public static void main(String[] args){//创建线程MyRunnable myRunnable = new MyRunnable();Thread t = new Thread(myRunnable);//启动t.start();}
}
1.3 使用匿名内部类创建Thread子类对象
//通过匿名内部类的方式创建线程
public class Dome3 {public static void main(String[] args) {//创建线程Thread t = new Thread(){@Overridepublic void run() {System.out.println("hello run");}};//启动线程t.start();}
}
1.4 使用匿名内部类创建Runnable子类对象
//使用匿名内部类创建Runnable子类对象
public class Dome4 {public static void main(String[] args) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("hello run");}});t.start();
}
1.5 使用lambda创建
//lambda实现线程
public class Dome5 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread( () -> {System.out.println("hello run");});t.start();}
}
2. Thread常见的构造方法
2.1 Thread()
//创建Thread对象
Thread t = new Thread();
2.2 Thread(Runnable target)
//使用Runnable对象创建线程对象
Thread t = new Thread(new Runnable);
2.3 Thread(String name)
//为这个线程命名
Thread t = new Thread("名字");
2.4 Thread(Runnable target, String name)
//使用Runnable对象创建线程对象并命名
Thraed t = new Thread(new Runnable,"名字");
3. Thread常见的属性
| 属性 | 获取方法 |
|---|---|
| ID | getId() |
| name | getName() |
| 状态 | getState() |
| 优先级 | getPriority() |
| 是否为后台线程 | isDaemon() |
| 是否存活 | isAlive() |
| 是否中断 | isInterrupted() |
public class Test4 {public static void main(String[] args) {Thread t = new Thread(() -> {//Thread.currentThread调用当前线程对象,相当于t,这个时候t还未初始化成功,不能直接使用System.out.println("ID: " + Thread.currentThread().getId());System.out.println("name: " + Thread.currentThread().getName());System.out.println("状态: " + Thread.currentThread().getState());System.out.println("优先级: " + Thread.currentThread().getPriority());System.out.println("是否为后台线程: " + Thread.currentThread().isDaemon());System.out.println("是否存活: " + Thread.currentThread().isAlive());System.out.println("是否中断: " + Thread.currentThread().isInterrupted());});t.start();}
}

注意:
- ID 是线程的唯一标识,不同线程不会重复
- 名称是各种调试工具用到
- 状态表示线程当前所处的一个情况,下面我们会进一步说明
- 优先级高的线程理论上来说更容易被调度到
- 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
- 是否存活,即简单的理解,为 run 方法是否运行结束了
4. 线程的使用
4.1 启动线程
前面我们已经知道了线程的创建,构造等方法,但这些其实都是准备工作,还没有真正的从底层创建出一个线程,只有调用start方法够才算真正的创建成功线程。
//直接调用就可以 t.start()
4.2 中断线程
当线程启动的时候,有时里面是循环,这时线程便不会停止,我们便要想办法中断线程。中断线程有个简单的方法直接使用Thread.stop()方法,但是,这种方法是unsafe,而且基本上已经deprecated。
所以我们调用interrupt()方法进行停止线程,但它并不会直接停止线程,而是对线程内进行标记,标记为Boolean类的true。这个时候我们再调用下面两个方法。
public static boolean interruputed();测试线程是否为中断状态,还执行后会标记清除为false。
public boolean isInterputed();测试线程是否为中断状态,但不清除标记。
添加标志符进行中断:
//中断线程,添加标志位
public class Test3 {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {//while(!Thread.currentThread().isInterrupted()){System.out.println(Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {
// e.printStackTrace();break;}}});//启动线程t1.start();//休眠3秒Thread.sleep(3000);t1.interrupt();}
}
注意:
如果休眠中中断线程,则会异常,反之,也是。
//中断线程,添加标志位
public class Test3 {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {
// while(!Thread.currentThread().isInterrupted()){try {Thread.sleep(100000);} catch (InterruptedException e) {e.printStackTrace();System.out.println("异常!");}
// }System.out.println("end!");});t1.start();Thread.sleep(3000);t1.interrupt();System.out.println(t1.isInterrupted());System.out.println(Thread.interrupted());}
}

4.3 等待线程
| 方法 | 说明 |
|---|---|
| join() | 等待线程结束 |
| join(long millis) | 等待线程结束,最多等待millis毫秒 |
| join(long millis,int nanos) | 和2相比更加的精确 |
当我们同时启动几个线程,由于线程启动时随机无序的,我们无法得知谁先结束,这个时候就可以使用join方法让线程等待。
例如:当我们想让张三先上班,等张三上班结束,李四接班,那么我们就可以写出下面代码。
public class Test5 {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {while (!Thread.currentThread().isInterrupted()){System.out.println(Thread.currentThread().getName() + "在上班");try {Thread.sleep(1000);} catch (InterruptedException e ){break;}}},"张三");Thread t2 = new Thread(() -> {while(!Thread.currentThread().isInterrupted()){System.out.println(Thread.currentThread().getName() + "在上班");try {Thread.sleep(1000);} catch (InterruptedException e) {break;}}},"李四");System.out.println("监督张三");t1.start();Thread.sleep(3000);t1.interrupt();t1.join();System.out.println("监督李四");t2.start();Thread.sleep(3000);t2.interrupt();t2.join();}
}
4.4 休眠线程
线程在执行的时候是非常快的,这个时候我们就可以让线程执行一次后就休眠一定时间,便于更好的观察。
上面代码中我们也多次用到。
Thread.sleep(long millis),里面millis单位是毫秒。
相关文章:
【多线程】Thread类的用法
文章目录 1. Thread类的创建1.1 自己创建类继承Thread类1.2 实现Runnable接口1.3 使用匿名内部类创建Thread子类对象1.4 使用匿名内部类创建Runnable子类对象1.5 使用lambda创建 2. Thread常见的构造方法2.1 Thread()2.2 Thread(Runnable target)2.3 Thread(String name)2.4 Th…...
第八章 贪心算法 part03 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果 (day34补)
本文章代码以c为例! 一、力扣第1005题:K 次取反后最大化的数组和 题目: 给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组: 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择…...
Android Activity启动过程一:从Intent到Activity创建
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 目录 一、概览二、应用内启动源码流程 (startActivity)2.1 startActivit…...
第9章:聚类
聚类任务 性能度量 距离度量 非度量距离 原型聚类 有很好的统计学上的意义,但是只能找到椭球形的聚类。 密度聚类 层次聚类...
程序员为什么要写bug,不能一次性写好吗?
仅仅听到“Bug”这个词就会让你作为一个开发人员感到畏缩。我们相信,优秀的程序员是那些编写无错误代码的人。随着一些开发人员强调要成为一名零错误程序员,我们进行了更深刻的思考,并发现事实的准确性。 所有制作的软件都应该没有错误。对此…...
Nginx反向代理其他服务
Nginx反向代理 嘿,你的网络遇到了限制,不能直接通过服务的端口进行访问?别担心,我们可以借助Nginx这个超级英雄来解决这个问题!让我给你讲讲关于Nginx反向代理的故事吧。 首先,让我们明确一下反向代理的概…...
MQ 简介-RabbitMQ
一. MQ 简介 消息队列作为高并发系统的核心组件之一,能够帮助业务系统结构提升开发效率和系统 稳定性,消息队列主要具有以下特点: 削峰填谷:主要解决瞬时写压力大于应用服务能力导致消息丢失、系统奔溃等问题系统解耦:解决不同重要程度、不…...
强化学习(2)
强化学习(1) 1.多智能体深度强化学习重要性采样 多智能体深度强化学习(Multi-Agent Deep Reinforcement Learning,MADRL)是指在多智能体环境下使用深度强化学习算法进行协同学习。重要性采样(Importance Sampling)是…...
Visual Studio 2022的MFC框架——theApp全局对象
我是荔园微风,作为一名在IT界整整25年的老兵,今天我们来重新审视一下Visual Studio 2022下开发工具的MFC框架知识。 MFC中的WinMain函数是如何与MFC程序中的各个类组织在一起的呢?MFC程序中的类是如何与WinMain函数关联起来的呢?…...
SpringBoot Cache
一、基本概念 Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。 Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现,例如: • EHCache • Caffeine …...
vue 简单实验 自定义组件 component
1.代码 <script src"https://unpkg.com/vuenext" rel"external nofollow" ></script> <div id"components-demo"><button-counter></button-counter> </div> <script> // 创建一个Vue 应用 const ap…...
C++ 改善程序的具体做法 学习笔记
1、尽量用const enum inline替换#define 因为#define是做预处理操作,编译器从未看见该常量,编译器刚开始编译,它就被预处理器移走了,而#define的本质就是做替换,它可能从来未进入记号表 解决方法是用常量替换宏 语言…...
Unity 之 GameObject.Find()在场景中查找指定名称的游戏对象
文章目录 GameObject.Find 是 Unity 中的一个函数,用于在场景中查找指定名称的游戏对象。这个函数的主要作用是根据游戏对象的名称来查找并返回一个引用,使您能够在代码中操作该对象。以下是有关 GameObject.Find 的详细介绍: 函数签名&…...
flink on yarn with kerberos 边缘提交
flink on yarn 带kerberos 远程提交 实现 flink kerberos 配置 先使用ugi进行一次认证正常提交 import com.google.common.io.Files; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.flink.client.cli.CliFrontend; import o…...
NodeJS的简介以及下载和安装
本章节会带大家下载并安装NodeJs 以及简单的入门,配有超详细的图片,一步步带大家进行下载与安装 NodeJs简介关于前端与后端Node是什么?为什么要学习NodeNodeJS的优点: NodeJS的下载与安装NodeJS的下载: NodeJS的快速入…...
量化面试-概率题
文章目录 一、题目1.糖果罐(绿皮书79页)2 折木棍(绿皮书89页)3 第一张ACE(绿皮书95页)4 n个均匀分布之和(绿皮书95页) 二、答案1. 糖果罐2 折木棍3 第一张ACE4 n个均匀分布之和 一、…...
【spark】java类在spark中的传递,scala object在spark中的传递
记录一个比较典型的问题,先讲一下背景,有这么一个用java写的类 public class JavaClass0 implements Serializable {private static String name;public static JavaClass0 getName(String str) {if (name null) {namestr;}return name;}... }然后在sp…...
php 文字生成图片保存到本地
你可以使用PHP的GD库来生成图片并保存到本地。首先,你需要确保你的PHP环境已经安装了GD库。然后,你可以使用GD库的函数来创建一个画布,并在上面绘制文字。最后,使用imagepng或imagejpeg函数将画布保存为PNG或JPEG格式的图片文件。…...
面试手撕—二叉搜索树及其后序遍历
一、引言 在面试地平线的时候,聊到了二叉搜索树,让手撕二叉搜索树,以下是要求 1、用类模板实现二叉搜索树 2、写一个函数,实现给一个vector数组,转换成二叉搜索树 3、写出二叉搜索树的后序遍历 二、代码实现 #inc…...
Java数据结构面试题以及答案
本专栏记录Java后端开发相关的面试题,欢迎大家阅读专栏的其他文章。 目录 1.B树和B树的区别?B树和B树的优点分别是? 2.排序算法的种类和复杂度 3.HashMap和Hashtable的原理、区别、应用场景 4.ConcurrentHashMap的原理、应用场景 5.Arra…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
