【多线程】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…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...
内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献
Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译: ### 胃肠道癌症的发病率呈上升趋势,且有年轻化倾向(Bray等人,2018&#x…...
C++11 constexpr和字面类型:从入门到精通
文章目录 引言一、constexpr的基本概念与使用1.1 constexpr的定义与作用1.2 constexpr变量1.3 constexpr函数1.4 constexpr在类构造函数中的应用1.5 constexpr的优势 二、字面类型的基本概念与使用2.1 字面类型的定义与作用2.2 字面类型的应用场景2.2.1 常量定义2.2.2 模板参数…...
Ray框架:分布式AI训练与调参实践
Ray框架:分布式AI训练与调参实践 系统化学习人工智能网站(收藏):https://www.captainbed.cn/flu 文章目录 Ray框架:分布式AI训练与调参实践摘要引言框架架构解析1. 核心组件设计2. 关键技术实现2.1 动态资源调度2.2 …...
新版NANO下载烧录过程
一、序言 搭建 Jetson 系列产品烧录系统的环境需要在电脑主机上安装 Ubuntu 系统。此处使用 18.04 LTS。 二、环境搭建 1、安装库 $ sudo apt-get install qemu-user-static$ sudo apt-get install python 搭建环境的过程需要这个应用库来将某些 NVIDIA 软件组件安装到 Je…...
