多线程学习笔记--第一章 多线程技能(2)

2023-05-16

1.currentThread方法
该方法返回代码段正在被哪个线程调用的信息。

2.isAlive方法
判断当前线程是否处于活动状态。活动状态是线程已经启动且尚未终止。线程处于运行或准备开始运行的状态。
如果将线程对象以构造参数的方式传递给Thread对象进行start启动时,结果与直接启动由差异,原因来自于Thread.currentThread()和this的差异。

3.sleep方法
在指定的毫秒数内让当前“正在执行的线程”休眠。正在执行的线程是指this.currentThread返回的线程。

4.getId方法
取得线程唯一标识。

5.停止线程
停止线程就是在线程处理完任务之前停止操作。停止一个线程可以使用Thread.stop方法,但最好不用它。该方法不安全,已被弃用。多数停止一个线程的操作使用Thread.interrupt方法,但这个方法不会终止一个正在运行的线程,需要加入一个判断才能完成线程停止。
三种终止线程:

  1. 使用退出标志,使线程正常退出,也就是run方法完成后终止。
  2. 使用stop方法
  3. 使用interrupt方法

interrupt方法并不能使线程停止,仅仅在当前线程中打一个停止标记。

判断线程是否是停止状态:

  1. this.interrupted():测试当前线程是否已经中断。执行后具有将状态标志清除为false功能
  2. this.isInterrupted():测试线程是否已经中断。但不清除标志。

异常法停止线程

public class MyThread{

	public static void main(String[] args){
		try{
			Thread6 t6=new Thread6();
			t6.start();
			Thread.sleep(2000);
			t6.interrupt();
		}catch(InterruptedException e){
			System.out.println("main catch");
			e.printStackTrace();
		}
		System.out.println("end!");
	}
}


public class Thread6 extends Thread{
	/**
	 * 异常法停止线程
	 */
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		super.run();
		try{
			for(int i=0;i<500000;i++){
				if(this.interrupted()){
					System.out.println("已经是停止状态!退出!");
					throw new InterruptedException();
				}
				System.out.println("i="+(i+1));
			}
			System.out.println("我在for后面!线程还没有停止");
		}catch(InterruptedException e){
			System.out.println("进入Thread6.java的catch了!");
			e.printStackTrace();
		}
	}
}

i=209513
i=209514
i=209515
i=209516
i=209517
end!
已经是停止状态!退出!
进入Thread6.java的catch了!
java.lang.InterruptedException
	at Thread6.run(Thread6.java:14)

沉睡中停止


public class MyThread{

	public static void main(String[] args){
		try{
			Thread7 t7=new Thread7();
			t7.start();
			Thread.sleep(2000);
			t7.interrupt();
		}catch(InterruptedException e){
			System.out.println("main catch");
			e.printStackTrace();
		}
		System.out.println("end!");
	}
}


public class Thread7 extends Thread{

	/**
	 * 沉睡中停止线程
	 */
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		super.run();
		try{
			System.out.println("run begin");
			Thread.sleep(200000);
			System.out.println("run end");
		}catch(InterruptedException e){
			System.out.println("在沉睡中被停止,进入catch!"+this.isInterrupted());
			e.printStackTrace();
		}
	}
}

run begin
end!
在沉睡中被停止,进入catch!false
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at Thread7.run(Thread7.java:13)

可知,在sleep状态下停止某一线程,进入catch,并清除停止状态值,变为false。


public class MyThread{

	public static void main(String[] args){
		Thread8 t8=new Thread8();
		t8.start();
		t8.interrupt();
		System.out.println("end!");
	}
}


public class Thread8 extends Thread{

	/**
	 * 先停止,再sleep
	 */
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		super.run();
		try{
			for(int i=0;i<100000;i++){
				System.out.println("i="+(i+1));
			}
			System.out.println("run begin");
			Thread.sleep(200000);
			System.out.println("run end");
		}catch(InterruptedException e){
			System.out.println("先停止,再遇到sleep,进入catch!");
			e.printStackTrace();
		}
	}
}

i=99998
i=99999
i=100000
run begin
先停止,再遇到sleep,进入catch!
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at Thread8.run(Thread8.java:16)

与之相反的操作


public class MyThread{

	public static void main(String[] args){
		Thread9 t9=new Thread9();
		t9.start();
		t9.interrupt();
		System.out.println("end!");
	}
}


public class Thread9 extends Thread{
	/*
	 *先停止,再遇到sleep 
	 */
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		super.run();
		try{
			for(int i=0;i<100000;i++){
				System.out.println("i="+(i+1));
			}
			System.out.println("run begin");
			Thread.sleep(200000);
			System.out.println("run end");
		}catch(InterruptedException e){
			System.out.println("先停止,在进入sleep,进入catch!");
			e.printStackTrace();
		}
	}
}

i=99999
i=100000
run begin
先停止,在进入sleep,进入catch!
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at Thread9.run(Thread9.java:15)

暴力停止
使用stop方法停止线程。


public class MyThread{

	public static void main(String[] args){
		try{
			Thread10 t10=new Thread10();
			t10.start();
			Thread.sleep(8000);
			t10.stop();
			System.out.println("end!");
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
}


public class Thread10 extends Thread{

	/*
	 * 使用stop停止
	 */
	private int i=0;
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		try{
			while(true){
				i++;
				System.out.println("i="+i);
				Thread.sleep(1000);
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
}

i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
end!

方法stop与java.lang.ThreadDeath异常
调用stop时会抛出java.lang.ThreadDeath异常。通常情况下,不需要显示捕捉。
stop方法已经被废弃,因为如果强制让线程停止可能使一些清理性的工作得不到完成。对锁定的对象进行解锁,导致数据得不到同步处理,出现数据不一致。

释放锁的不良后果
使用stop释放锁会造成数据不一致性结果。


public class MyThread{

	public static void main(String[] args){
		try{
			SynchronizedObject object=new SynchronizedObject();
			Thread11 t11=new Thread11(object);
			t11.start();
			Thread.sleep(500);
			t11.stop();
			System.out.println(object.getUsername()+" "+object.getPassword());
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
}


public class SynchronizedObject {

	/*
	 * stop释放锁
	 */
	private String username="a";
	private String password="aa";
	public String getUsername(){
		return username;
	}
	
	public void setUsername(String username){
		this.username=username;
	}
	
	public String getPassword(){
		return password;
	}
	
	public void setPassword(String password){
		this.password=password;
	}
	
	synchronized public void printString(String username,String password){
		try{
			this.username=username;
			Thread.sleep(100000);
			this.password=password;
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
	
}


public class Thread11 extends Thread{
	/*
	 * stop释放锁
	 */

	private SynchronizedObject object;
	public Thread11(SynchronizedObject object){
		super();
		this.object=object;
	}
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		object.printString("b", "bb");
	}
}

使用return停止线程
将方法interrupt与return结合可以实现停止线程效果。


public class MyThread{

	public static void main(String[] args){
		Thread12 t12=new Thread12();
		t12.start();
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		t12.interrupt();
	}
}


public class Thread12 extends Thread{

	/*
	 * 使用return+interrupt停止线程
	 */
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		while(true){
			if(this.isInterrupted()){
				System.out.println("stop!!!");
				return;
			}
			System.out.println("timer="+System.currentTimeMillis());
		}
	}
}

timer=1550561473006
timer=1550561473006
timer=1550561473006
timer=1550561473006
stop!!!

建议使用“抛出异常”方法来实现线程停止,因为catch中的异常还可以向上抛,使得线程停止事件得以传播。

参考书籍《java多线程编程核心技术》

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多线程学习笔记--第一章 多线程技能(2) 的相关文章

  • 寻路系统:动态障碍物

    寻路的相关参数 需要先勾选 游戏场景中所有需要烘焙路径信息的游戏对象状态为 static 然后点开windos菜单下的navigation窗口进行烘培 Navigation Static xff1b 表示该游戏对象是否参与导航网格的烘培 G
  • Ubuntu18.04下使用cmake编译一个OpenCV程序(编写CMakeLists.txt文件)

    导航 1 安装OpenCV1 1首先安装OpenCV 1 2定位OpenCV 2 创建一个项目3 编写一个基础OpenCV程序4 编写CMakeLists txt文件 为了记录以及防止遗忘 xff0c 备份一个大致能满足运行的CMakeLi
  • linux下最全curl命令使用方式学习和拓展

    为什么要使用curl命令 xff1f curl命令可以帮助我们在linux服务内部通讯 xff0c 排查接口是否能够正确调用 xff0c 外网的接口是否有防火墙限制 xff0c 内网的请求可以快速帮我们获取接口参数返回 xff0c 并且调试
  • 【传感器标定】kalibr 标定工具箱问题汇总

    文章目录 写在前面一 运行一段时间报错 96 Spline Coefficient Buffer Exceeded Set larger buffer margins 96 的解决方法1 问题描述2 解决方法参考链接 写在前面 kalibr
  • C++中的Vector存放指针的清空问题

    C 43 43 中的Vector存放指针的清空问题 一 写在前面二 参考做法参考链接 这两个链接写得挺好 xff0c 可以参考下 一 写在前面 C 43 43 很难的一个重要原因就是内存管理的问题 xff0c 因为你既要管理申请内存 xff
  • find_package(xxxx REQUIRED)找不到路径的全平台通用解决办法

    相信刚学cmake c 43 43 的朋友们在编译的时候一定被这个问题折磨许久哈 然后怎么搜怎么添加都有问题 xff0c 仔细研究了我才发现这个地方不同的索引机制 xff0c 但是表面上都是 find package xxxx REQUIR
  • STC51-串口通信

    1 并行与串行基本通信方式 随着单片机系统的广泛应用和计算机网络技术的普及 xff0c 单片机的通信功能愈来愈显得重要 单片机通信是指单片机与计算机或单片机与单片机之间的信息交换 xff0c 通常单片机与计算机之间的通信我们用的较多 通信有
  • qt种实现搜索栏功能

    引言 在搜索栏种输入要搜索的文本 xff0c 就会出现相关联的文本提示 xff0c 这是可以通过鼠标选中要搜索的文本 xff0c 或者通过上下键选中要搜索的文本 效果 效果图如下所示 xff1a 实现 下面是相关的代码实现 xff0c 读者
  • orangePi3 TLS烧录启动、wifi配置和ssh登录、烧录进内置emmc flash

    orangePi3 TLS烧录启动 wifi配置和ssh登录 烧录进内置emmc flash 烧录镜像到TF卡启动 镜像下载 官方镜像地址 xff1a http www orangepi cn html hardWare computerA
  • C/C++——代码的编译和运行

    1 编译过程 每种高级语言都有对应的编译器 xff0c 而且针对不同指令集架构的CPU会提供不同的编译器 本文以C语言为例 xff0c CPU指令集架构不做前提约束 xff0c 实际上同一种语言也只有在狭义的编译阶段有所区别 xff0c 其
  • Arduino UNO GPS 制作 里程表 经纬度

    机缘 上过月买了一个GPS模块 xff0c 然后我用esp32读取GPS数据 xff0c 并使用LVGL显示GPS信息 期间踩了很多坑 xff0c 我用乐鑫的IDF开发 xff0c 自己写了一个GPS信息提取方法 xff0c BUG很多 x
  • socket编程——UDP协议(C语言编程)

    1 收发信息 ssize t sendto int socket void message size t length int flags struct sockaddr dest addr socklen t dest len 返回值 l
  • 【C语言之线性表链式存储结构】

    C语言之线性表链式存储结构 文章目录 C语言之线性表链式存储结构前言一 线性表链式存储结构定义二 相关概念1 结点1 头指针 三 代码描述1 单链表结点定义1 单链表的创建2 单链表的查找3 在单链表中 xff0c 替换某一个位置的数据4
  • unsigned char* (uchar*) 转为QImage

    场景 xff1a 有一副图像 xff0c 事先已经因为各种需要被读取到了内存中 xff0c 且不可再根据路径读取 xff0c 只能读取内存中的数据转为QImage 百度过好久 xff0c 没有一个帖子说的特别详细 xff0c 解释的特别清楚
  • 卷积的含义-详解

    原文链接 xff1a 点击此处看知乎原文 最近需要用到卷积对图像进行处理 xff0c 不明白卷积的含义 xff0c 找资料的时候在知乎找到一个很优秀的评论 xff0c 特此记录一下 以下内容来自于原文复制 xff1a 对卷积的困惑 卷积这个
  • 图像处理-直方图均衡化(C++实现,不依赖opencv)

    近来接触图像处理领域 xff0c opencv入门之后 xff0c 想自己动手实现一些算法 xff0c 先从直方图均衡化开始吧 xff01 我使用的图像文件是只包含数据yuv格式图像 xff0c 以后等需要的时候再处理从普通格式 xff08
  • 图像处理-Sobel边缘检测(C++实现,不依赖opencv)

    边缘检测一直是图像处理中比较热门的一块 xff0c 今天简单实现了下sobel算法 先上图 xff1a 原图 xff1a Sobel处理 彩图 xff1a Sobel处理 灰度图 xff1a 可以看到在不复杂的情况下 xff0c Sobel
  • 图像处理-高斯滤波和升级版Side Window版高斯滤波(C++实现,无需opencv)

    图像处理绕不开的一个环节就是去燥 xff0c 去掉各式各样的噪声来保证图像的质量 今天将高斯滤波实现了下 xff0c 在此稍作记录 以往惯例 xff0c 先上图 xff1a 原图 xff1a 高斯滤波 xff1a Side Window版高
  • Linux下,使用nginx+ffmpeg+video.js实现直播效果(含centos7环境配置步骤)

    前言 近来因为项目需要 xff0c 需要做一个把视频解码然后推流 xff0c 在浏览器播放的功能 然后查资料 找demo xff0c 最终决定使用FFmpeg 43 nginx来完成相应功能 xff0c 过程颇为心酸 xff0c 在此做下笔
  • 使用QMap保存数据时,若出现相同的键,可以在不改变原有的变量存储选型基础上,使用insertMulti函数来解决

    场景 问题发生场景解决办法方案一方案二方案三 xff08 重点 xff09 针对方案三的示例 问题发生场景 本来项目中选型选择的是QMap来存储相应的键值对 xff0c 根据Map中的键的顺序取出对应的值 但是在使用的过程中 xff0c 发

随机推荐

  • C语言,声明和实现放在头文件中

    将头文件和实现放在同一个文件中 普通函数与静态函数是有区别的 静态函数 xff1a static h ifndef CRND INCLUDE CRND H define CRND INCLUDE CRND H static int pore
  • C++的编译过程详解

    C C 43 43 编译过程 C C 43 43 编译过程主要分为4个过程 编译预处理编译 优化阶段汇编过程链接程序 一 编译预处理 xff08 1 xff09 宏定义指令 xff0c 如 define Name TokenString x
  • BA(Basic authentication)认证实践

    1 概念介绍 Basic authentication xff1a 是一种最简单的对Web资源进行访问控制的方法 xff0c 属应用层的安全保障手段 常用的签名算法有 xff1a base64 HmacSHA1 1 xff09 优点 xff
  • 累加校验和C语言实现

    发送方 xff1a 对要数据累加 xff0c 得到一个数据和 xff0c 对和求反 xff0c 即得到我们的校验值 然后把要发的数据和这个校验值一起发送给接收方 接收方 xff1a 对接收的数据 包括校验和 进行累加 xff0c 如果得到0
  • C++项目工程在Linux环境开发、部署和运行问题

    背景 当我们自己开发的项目程序需要在linux上进行部署 调试时 xff0c 项目代码完整拷贝过去之后 xff0c 直接运行我们自己的可执行程序 xff0c 往往提示找不到所相关的 so库 xff0c 会报错 这是因为 xff0c 系统只会
  • Jetson Xavier NX上安装ROS、Cartographer、基于D435i的Yolov5+TensorRT7的流程及问题解决

    主要记录下自己在Jetson Xavier NX上运行ROS Cartographer 基于D435i的Yolov5 43 TensorRT的系统环境配置流程 xff0c 经过了无数次在ARM上的安装 xff0c 这次是最流畅的一次环境配置
  • 计算机进制转换:二进制、八进制、十进制、十六进制

    一 什么是进制 在生活中 xff0c 我们通常都是使用阿拉伯数字计数的 xff0c 也就是10进制 xff0c 以10为单位 xff0c 遇10进一 xff0c 所以是由0 xff0c 1 xff0c 2 3 4 5 6 7 8 9组成的
  • 摘要认证,使用HttpClient实现HTTP digest authentication

    文章目录 前言一 四个过程二 过程细节三 HttpClient 代码示例 前言 今天工作需要做了摘要认证 xff08 digest authentication xff09 xff0c 下面就工作中遇到的问题及过程做一个总结 一 四个过程
  • C语言之带参数的宏

    这两天在学习C语言 xff0c 发现宏定义挺有意思 xff0c 可以减少代码量 带参宏定义 的一般形式为 define 宏 名 形参表 字符串 带参宏调用 的一般形式为 xff1a 宏 名 实参表 xff1b define M X Y X
  • visual studio升级

    visual studio升级 概述升级步骤温馨提示 概述 有时处于开发要求或者安全要求 xff0c 需要将visual studio升级到最新的版本 本篇文章记录一下如何升级 升级步骤 1 找到visual studio的安装路径下的安装
  • STL中那些好用的东西!(持续更新)

    一 数据结构部分 1 set amp map xff08 后续持续更新 xff09 2 queue xff08 priority queue xff09 queue lt int gt a 定义 a push i 压入 a pop 弹出 a
  • 工业机器人虚拟仿真设计

  • HTTP详解

    一 什么是HTTP xff1f HTTP xff08 HyperText Transfer Protocol xff0c 超文本传输协议 xff09 是一个简单的请求 响应协议 xff0c 它通常运行在TCP之上 xff08 应用层 xff
  • android练习之为 TextView 添加监听器 ,添加后退按钮 ,从按钮到图标按钮

    为 TextView 添加监听器 NEXT按钮不错 xff0c 但如果用户单击应用的TextView文字区域 xff08 地理知识问题 xff09 xff0c 也可以跳转 到下一道题 xff0c 用户体验会更好 添加后退按钮 为GeoQui
  • ORA-01918: 用户 'SCOTT' 不存在 解决方法

    SQL gt alter user scott account unlock alter user scott account unlock 第 1 行出现错误 ORA 01918 用户 SCOTT 不存在 找到scott sql 文件 S
  • idea 里form表单action提交servlet文件出现报错

    由于在action的字符串中加了空格 xff0c 导致于于url pattern不匹配 xff0c 所以报错
  • 数据结构——二维数组

    二维数组可以理解为数组的数组 二维数组组织为矩阵 xff0c 可以表示为行和列的集合 但是 xff0c 创建二维数组以实现关系数据库外观相似的数据结构 它提供了一次容纳大量数据的便利性 xff0c 可以在任何需要的地方传递给任意数量的功能
  • 数据结构——链表

    链表是一种随机存储在内存中的节点的对象集 节点包括两个字段 xff0c 即存储在该地址的数据和包含下一节点地址的指针 链表的最后一个节点包含指向null的指针 1 链表的用途 链表不需要连续存在于存储器中 节点可以是存储器中任何位置并链接在
  • 多线程学习笔记--第一章 多线程技能(1)

    1 什么是进程 xff1f 进程是操作系统结构的基础 xff0c 是一次程序的执行 xff1b 是一个程序及其数据在处理机上顺序执行时所发生的活动 xff1b 是程序在一个数据集合上运行的过程 xff0c 它是系统进行资源分配和调度的一个独
  • 多线程学习笔记--第一章 多线程技能(2)

    1 currentThread方法 该方法返回代码段正在被哪个线程调用的信息 2 isAlive方法 判断当前线程是否处于活动状态 活动状态是线程已经启动且尚未终止 线程处于运行或准备开始运行的状态 如果将线程对象以构造参数的方式传递给Th