多线程异常 和 事务(一)

2023-11-05

1,首先提出几个问题:

1.1,子线程中的异常在主线程中是否可以catch

1.2,在spring中主线程有事务,那么子线程中有事务码

2,先看第一个问题

2.1,我们在main方法里面测试,代码如下

package com.pingan.test.call;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


public class MutiThreadException {

	
	public static void main(String[] args) {
		System.out.println("MutiThreadException.main()------>start<------");
		try {
			List<Future<Object>> resultList = new ArrayList<Future<Object>>();  
//			ExceptionHandle exceptionHandle = new ExceptionHandle();
			ExecutorService service=Executors.newFixedThreadPool(6);
			for (int i = 0; i < 3; i++) {
				Thread t=new Thread(new  Runnable() {
					@Override
					public void run() {
						System.out.println("id "+Thread.currentThread().getName()+"---start>");
						if(Thread.currentThread().getName().endsWith("2")){
//							int i=1/0;
							  throw new RuntimeException();  
						}
						try {
							Thread.sleep(2000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println("id "+Thread.currentThread().getName()+"----end:");
					}
				});
//				t.setUncaughtExceptionHandler(new ExceptionHandle());
				t.start();
//				Future<Object> future = (Future<Object>) service.submit(t);
//				resultList.add(future);
			}
//			for(Future f:resultList){
//				Object o=f.get();
//				System.out.println(o);
//			}
//			service.shutdown();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("MutiThreadException.main()------>end<------");
	}
}

run后的结果如下

MutiThreadException.main()------>start<------
id Thread-0---start>
id Thread-1---start>
MutiThreadException.main()------>end<------
id Thread-2---start>
Exception in thread "Thread-2" java.lang.RuntimeException
	at com.pingan.test.call.MutiThreadException$1.run(MutiThreadException.java:26)
	at java.lang.Thread.run(Thread.java:662)
id Thread-0----end:
id Thread-1----end:
可以看出日志打印了异常,是否就说明我们catch到了异常呢,答案:否。我们可以吧catch中的 e.printStackTrace()注释,然后再次运行,会发现结果依然一样。
什么原因呢,其实是异常在子线程中逃逸到了控制台,并没有被主线程catch到。thread的run方法不允许抛出异常,所以我们要在线程里自己处理,对于运行时异常如果没有catch那么就逃逸到控制台。
当然API也提供了一个接口UncaughtExceptionHandler,我们实现就可以然后在set到线程中,代码如下
package com.pingan.test.call;

import java.lang.Thread.UncaughtExceptionHandler;

public class ExceptionHandle implements UncaughtExceptionHandler{

	@Override
	public void uncaughtException(Thread t, Throwable e) {
		System.out.println("ExceptionHandle.uncaughtException()");
	}

	
}

2.2,我们把测试代码中的这一行注释掉t.setUncaughtExceptionHandler(new ExceptionHandle());
run后的结果如下:

MutiThreadException.main()------>start<------
id Thread-0---start>
id Thread-1---start>
MutiThreadException.main()------>end<------
id Thread-2---start>
ExceptionHandle.uncaughtException()
id Thread-1----end:
id Thread-0----end:

可以看到异常被内部捕获处理掉,但是id Thread-2---end没有打印,说明线程异常后直接结束了,没有走下面的代码。所以我觉得这个接口没有实际的应用场景。

2.3,如果要是用线程池呢

我们注释掉这两行

t.setUncaughtExceptionHandler(new ExceptionHandle());

t.start();

这两行放开注释 

Future<Object> future = (Future<Object>) service.submit(t);

service.shutdown();

Run代码运行如下

MutiThreadException.main()------>start<------
MutiThreadException.main()------>end<------
id pool-1-thread-1---start>
id pool-1-thread-2---start>
id pool-1-thread-3---start>
id pool-1-thread-1----end:
id pool-1-thread-3----end:

可以看到控制台没有异常,说明ExecutorService已经处理过了,那我们怎么知道子线程是否有异常呢,代码中我们看到submit是有返回值的,修改测试代码如下

package com.pingan.test.call;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


public class MutiThreadException {

	
	public static void main(String[] args) {
		System.out.println("MutiThreadException.main()------>start<------");
		ExecutorService service=null;
		try {
			List<Future<Object>> resultList = new ArrayList<Future<Object>>();  
//			ExceptionHandle exceptionHandle = new ExceptionHandle();
			service=Executors.newFixedThreadPool(6);
			for (int i = 0; i < 3; i++) {
				Thread t=new Thread(new  Runnable() {
					@Override
					public void run() {
						System.out.println("id "+Thread.currentThread().getName()+"---start>");

						if(Thread.currentThread().getName().endsWith("1")){
							try {
								Thread.sleep(2000);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
							int i=1/0;
//							  throw new RuntimeException();  
						}
						if(Thread.currentThread().getName().endsWith("2")){
							try {
								Thread.sleep(1000);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
//							int i=1/0;
							  throw new RuntimeException();  
						}
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println("id "+Thread.currentThread().getName()+"----end:");
					}
				});
//				t.setUncaughtExceptionHandler(new ExceptionHandle());
//				t.start();
				Future<Object> future = (Future<Object>) service.submit(t);
				resultList.add(future);
			}
			System.out.println("resultList.size:"+resultList.size());
			for(Future<Object> f:resultList){
				System.out.println("f------>"+f);
				Object o=null;
//				try {
					o=f.get();
//				} catch (ExecutionException  e) {
//					e.printStackTrace();
//				}
//				System.out.println(o);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			service.shutdown();
		}
		System.out.println("MutiThreadException.main()------>end<------");
	}
}


Run运行结果如下

MutiThreadException.main()------>start<------
id pool-1-thread-1---start>
id pool-1-thread-2---start>
resultList.size:3
id pool-1-thread-3---start>
f------>java.util.concurrent.FutureTask@7d67d940
id pool-1-thread-3----end:
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
	at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
	at java.util.concurrent.FutureTask.get(FutureTask.java:83)
	at com.pingan.test.call.MutiThreadException.main(MutiThreadException.java:63)
Caused by: java.lang.ArithmeticException: / by zero
	at com.pingan.test.call.MutiThreadException$1.run(MutiThreadException.java:33)
	at java.lang.Thread.run(Thread.java:662)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
	at java.lang.Thread.run(Thread.java:662)
MutiThreadException.main()------>end<------

这个里面信息还是比较多的,可以看到线程1和2都没有结束,打印的异常是线程1抛出的异常,线程1一共休眠了3秒,线程2休眠了2秒,为什么线程1的异常打印了而没有打印1的异常呢?为什么?为什么呢?
这里要怪我烦的错误,我们是吧Futrue放到List里面然后遍历获取的,肯定是按顺序获取线程1,2,3的结果的,当获取1的时候f.get方法就抛了异常了,方法直接就结束了。所以我们修改代码吧f.get()方法try/catch住,捕获ExecutionException捕获执行异常,再次运行

MutiThreadException.main()------>start<------
id pool-1-thread-1---start>
id pool-1-thread-2---start>
resultList.size:3
id pool-1-thread-3---start>
f------>java.util.concurrent.FutureTask@2ce83912
id pool-1-thread-3----end:
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
	at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
	at java.util.concurrent.FutureTask.get(FutureTask.java:83)
	at com.pingan.test.call.MutiThreadException.main(MutiThreadException.java:63)
Caused by: java.lang.ArithmeticException: / by zero
	at com.pingan.test.call.MutiThreadException$1.run(MutiThreadException.java:33)
	at java.lang.Thread.run(Thread.java:662)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)null
f------>java.util.concurrent.FutureTask@4318f375

	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
	at java.lang.Thread.run(Thread.java:662)
java.util.concurrent.ExecutionException: java.lang.RuntimeException
	at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
	at java.util.concurrent.FutureTask.get(FutureTask.java:83)
	at com.pingan.test.call.MutiThreadException.main(MutiThreadException.java:63)
Caused by: java.lang.RuntimeException
	at com.pingan.test.call.MutiThreadException$1.run(MutiThreadException.java:43)
	at java.lang.Thread.run(Thread.java:662)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
	at java.lang.Thread.run(Thread.java:662)
null
f------>java.util.concurrent.FutureTask@1b17a8bd
null
MutiThreadException.main()------>end<------

这次看到两个异常都捕获到了我们在主线程拿到了子线程抛出的异常。上面犯错要反省一下,什么原因导致我烦的错误呢,就是我在最外面用EXCEPTION捕获的所有异常,所以eclipse没有提示f.get()方法的异常。我们应该在for循环的里面捕获异常,让循环走下去。日志还有一个信息那就是返回值我们看到是null,因为thread的run方法确实没有返回值。


感觉文章有点长了,下面文章接着继续,我们在spring中看下关于事务的问题

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

多线程异常 和 事务(一) 的相关文章

  • 指纹奇异点检测

    我正在尝试确定指纹的核心点和增量点 我正在使用庞加莱指数方法 但我无法成功检测到这一点 而且我不明白为什么 First I divide the image in 15x15 blocks then I calculate the x an
  • 如何防止在 CXF Web 服务客户端中生成 JAXBElement

    我正在尝试使用 CXF 创建一个 Web 服务客户端来使用 WCF Web 服务 当我使用 wsdl2java 时 它生成具有 JAXBElement 类型而不是 String 的对象 我读到有关使用 jaxb bindings xml 文
  • 如何在Mac上使用eclipse安装jetty

    我是一个新手 jetty 和 RESTful API 我想使用 Jetty 创建 REST 服务 并希望将嵌入式 jetty 与 eclipse 一起使用 任何人都可以建议我在 Mac OS 中使用 Eclipse 安装 Jetty Jet
  • 在 Android 中绘制一条带有弯曲边缘的线

    I am using canvas drawLine to draw some line in android but the lines are too sharp but i need a curved edges 这里的 1 是我所拥
  • WebLogic 10 中的临时目录

    每当 WL 停止时 它都不会删除其临时目录 即 domains mydomain servers myserver tmp WL TEMP APP DOWNLOADS domains mydomain servers myserver tm
  • 使用 JAXB 编组 LocalDate

    我正在构建一系列链接类 我希望能够将其实例编组到 XML 以便我可以将它们保存到文件中并稍后再次读取它们 目前我使用以下代码作为测试用例 import javax xml bind annotation import javax xml b
  • 如果按下 Esc 则中断循环

    我用 JAVA 语言编写了一个程序 它使用 Scanner 类接受来自控制台的输入 现在我想将此功能添加到我的代码中 以便在用户按下 Esc 按钮时存在循环 while 到目前为止 我认为键盘类可以帮助我 但它就像扫描仪一样 我尝试使用事件
  • BigDecimal 的 JPA @Size 注释

    我该如何使用 SizeMySQL 的注释DECIMAL x y 列 我在用着BigDecimal 但是当我尝试包括 Size max它不起作用 这是我的代码 Size max 7 2 Column name weight private B
  • JavaFx 中装饰且不可移动的舞台

    我想在 JavaFx 中创建一个装饰舞台 它也将不可移动 我正在从另一个控制器类创建这个阶段 我能够创造和展示舞台 但它是自由移动的 我怎样才能创建这个 非常感谢帮助和建议 我把打开新关卡的方法贴出来 private void addRec
  • Scala(或 Java)中泛型函数的特化

    是否可以在 Scala 中专门化泛型函数 或类 例如 我想编写一个将数据写入 ByteBuffer 的通用函数 def writeData T buffer ByteBuffer data T buffer put data 但由于 put
  • 如何获取 Android 中临时文件的文件大小?

    如果我使用 openFileOutput 创建并写入临时文件 写入完成后如何获取文件大小 我希望这可以帮助你 File file new File selectedPath int file size Integer parseInt St
  • 删除 ArrayList 对象问题

    我在处理作业时遇到从 ArrayList 中删除对象的问题 如果我使用 正常 for 循环 它的工作原理如下 public void returnBook String isbn for int i 0 i lt booksBorrowed
  • 膨胀类片段 InflateException 二进制 XML 文件时出错

    我正在使用 Material Design 和 NavigationDrawer 布局等设计我的第一个应用程序 但我遇到了一个问题 该应用程序非常简单 它只显示文本 并且基于 Android Studio 中提供的模板 尝试启动我的应用程序
  • C++ 中的 Java ArrayList [重复]

    这个问题在这里已经有答案了 在Java中我可以做 List
  • 在 netBeans 中运行程序时,字体看起来非常奇怪

    我在我的新 MacBook M1 上设置了 netBeans 和 SceneBuilder 除了运行程序时的字体外 一切正常 它看起来像这样 我不知道为什么 按钮应显示 Click me 标签应显示 Hello 我收到的错误消息是 M rz
  • setKeyListener 将覆盖 setInputType 并更改键盘

    大家好 我在两个设备之间遇到问题 在实践中使用InputType和KeyListener我正在操纵一个EditText让它从数字键盘接收逗号和数字 有关更多背景信息 请检查我之前的question https stackoverflow c
  • 使用 Cucumber Scenario Outline 处理 Excel 电子表格

    如果可能的话 我试图找到一种更优雅的方法来处理从与 Excel 电子表格行 第 n 个 相关的 Cucumber Scenario Outline 中调用第 n 个数字 目前 我正在使用迭代编号来定义要从中提取数据的 Excel 电子表格的
  • Jenkins 管道和 java.nio.file.* 方法的问题

    我正在尝试使用 java nio file 中的方法在 Jenkins 管道中执行一些基本文件操作 无论代码存在于哪个节点块中 代码都在主节点上执行 在管道中 我已经验证了各个节点块都是正确的 它们唯一地标识了特定的节点 但是 pathEx
  • 如何使用maven创建基于spring的可执行jar?

    我有一个基于 Maven 的 Spring WS 客户端项目 我想将其打包为单个 jar 在eclipse中 一切运行正常 当我尝试将其打包为可执行 jar 时 我收到 ClassNotFound 异常 因为 Spring jar 未包含在
  • 编译时在代码中替换Java静态最终值?

    在java中 假设我有以下内容 fileA java class A public static final int SIZE 100 然后在另一个文件中我使用这个值 fileB java import A class b Object t

随机推荐

  • VBA中的Application.Calculation,公式的计算方式

    VBA经典应用69例 10178981 是我推出的第九套教程 教程是专门针对初级 中级学员在学习VBA过程中可能遇到的案例展开 这套教程案例众多 紧贴 实战 并做 战术总结 以便大家能很好的应用 教程的目的是要求大家在实际工作中要利用好VB
  • 目标检测论文解读复现之六:基于YOLOv5的遥感图像舰船的检测方法

    目标检测论文解读复现 文章目录 目标检测论文解读复现 前言 一 摘要 二 网络模型及核心创新点 三 应用数据集 四 实验效果 五 实验结论 六 投稿期刊介绍 前言 此前出了目标改进算法专栏 但是对于应用于什么场景 需要什么改进方法对应与自己
  • 【实战】Python爬虫之代理使用详解

    在Python爬虫中 代理的使用非常常见 代理的主要作用是隐藏客户端的真实IP地址 从而实现更高的网络访问速度和更好的访问隐私保护 下面我们将通过Python爬虫的实例 带你详细了解Python爬虫中代理的使用方法 目录 1 代理原理和作用
  • 随机生成小球(万家灯火的感觉)

    事发年前 新冠之前 拿到一张psd 全部静态 老板说想让他动起来 在我们这种老板吃死技术的小公司只能自己想办法 你想要ui no我们只有美工哈哈哈 独立自强的我瞬间想到transition enter leave cubic bezier之
  • 利用Python进行心脏病患者特征分析

    今天要跟大家说到的一个数据集分析 是关于心脏病的 心脏病作为全球第一大杀手 是我们不得不提前防御的疾病 今天我们利用Python从一份心脏病数据集中找出一些规律 看下哪些特征对于确诊心脏病影响比较大 从而提醒我们注意平时的生活规律 数据集介
  • 解决报错error resource androidattrdialogCornerRadius not found

    解决报错error resource android attr dialogCornerRadius not found 1 问题描述 运行Android Studio程序 产生报错error resource android attr d
  • 计算机大三学生怎么找实习工作?学了计算机很迷茫怎么办?

    学了计算机很迷茫怎么办呢 很多计算机大三学生找不到实习工作 也不知道从哪找实习工作 甚至常常怀疑自己的学习有没有意义 今日就由小编为大家简要介绍下吧 学了计算机很迷茫怎么办 学了计算机很迷茫怎么办呢 经常有很多学生发生这样的感慨 事实上绝大
  • sklearn中的fit_transform和transform以及什么时候使用

    在使用sklearn对数据进行预处理的时候很有可能会遇到fit transform和transform 网上不少资料写的模棱两可 在这里我回答几个核心问题 也许看完我写的这篇文章 一些疑惑就会豁然开朗 为什么在训练集进行fit而不在测试集f
  • c++的并归排序怎么写

    答 C 的并归排序的写法如下 1 如果数组只有一个元素 则返回该元素 2 否则 将数组分成两半 3 使用递归 对每一半进行并归排序 4 将排序后的两个子数组合并 5 返回排序后的结果
  • C语言回调函数一个简单的例子

    回调函数通俗的解释 普通函数 你所写的函数调用系统函数 你只管调用 不管实现 回调函数 系统调用你所写的函数 你只管实现 不管调用 以下是使用 语言实现回调函数的一个例子 代码 include
  • Microsoft Excel 无法插入新的单元格,因为这会将非空单元格推送到工作表的末尾...的问题解决

    这个问题的出现应该是最后一行或一列有数据 按以下步骤操作 1 选中文字表格最后一列空白列 随后按ctrl shift 向右 选中整列 点击右键删除 2 选中文字表格最后一行空白列 随后按ctrl shift 向右 选中整行 点击右键删除
  • Springboot 集成 Groovy Script 完整示例

    Springboot 集成 Groovy Script 完整示例 使用Spring Boot集成Groovy Script来实现动态规则解析和执行的Demo 以下是实现步骤 1 创建Spring Boot项目 首先 创建一个Spring B
  • 测试代码(测试函数、测试类)

    测试函数 def get name first last full name first last return full name title from name import get name print Enter q at any
  • Using a Single Business Pattern with the RUP -part3

    Using IBM Patterns for e business during inceptionKey goals of the RUP inception phase are A vision that establishes the
  • 逆向工程Python爬虫——国税局发票查验平台

    前言 这是一篇含金量很高的干货文章 笔者将手把手带领各位一步一步地实现爬取国家税务总局全国增值税发票查验平台 以下简称 查验平台 这个想法诞生在19年初 当时在做一款通过扫描二维码就可以查验发票的小程序 当时由于笔者学艺尚浅 没办法模拟请求
  • 浏览器localStorage

    Window localStorage 属性 JavaScript 存储对象 JavaScript 存储对象 实例 使用 localStorage 创建一个本地存储的 name value 对 name lastname value Smi
  • 解决jupyter notebook打开时找不到想要的文件

    原因 打开notebook默认显示的是当前目录下的文件 标题 解决办法 打开cmd用dos命令将当前目录切换到想用notebook打开的文件所在的文件夹 已经切换到了文件所在的目录 所以用命令jupyter notebook打开notebo
  • 重装pytorch历程-问题-解决

    用conda install时报错 An HTTP error occurred when trying to retrieve this URL HTTP errors are often intermittent 我要做的事 想使用to
  • 微软D365 入门文章汇总以及各项认证介绍(持续跟新.....)

    介绍 希望入门D365的同学们 需要具备的知识点 涉及C WebApi 前端知识 Power Platform等知识 以及Azure的知识点等 需要有了解 实施Microsoft Dynamics 365 CE 12章 实施Microsof
  • 多线程异常 和 事务(一)

    1 首先提出几个问题 1 1 子线程中的异常在主线程中是否可以catch 1 2 在spring中主线程有事务 那么子线程中有事务码 2 先看第一个问题 2 1 我们在main方法里面测试 代码如下 package com pingan t