为什么要干掉一个线程,这个和更健壮的系统有什么关系。
有时候我会想到一个问题,开发的系统基本上就是自己/测试团队测试了几遍然后上线。
上线后出现了不可预知的bug怎么办呢,例如出现了死循环或者部分逻辑有问题导致用户点击后会找出非常长的时间等待而且没办法进行其他操作。
java里面很多业务都用到了多线程,业务都放在线程池里面写
Thread.interrupt() 是无法终止一个非阻塞线程的,只能用Thread.stop()
stop()方法又不是推荐方法,不安全并@Deprecated了 但是又只有stop这个方法才能解决死循环
那么我们可以折中下,万不得已的情况才stop()
核心代码:先判断线程的状态,超时的线程又是RUNNABLE状态肯定是死循环了,其他情况使用中断方法。
// 获取到了执行该任务的线程 Thread execThread = (Thread) runner.get(obj); if (execThread == null) { return; } State state = execThread.getState(); if (state == State.RUNNABLE) { execThread.stop();// 非阻塞线程才STOP,例如死循环 } else { // 其他情况使用interrupt()方式,例如sleep、wait等等 } future.cancel(true);
完整代码:中断线程池里面的一个FutureTask
public void killThread(FutureTask<?> future) { try { if (future.isDone()) { return; } // 处理长时间超时的线程 // 利用反射,强行取出正在运行该任务的线程 // Thread属性藏在FutureTask.Sync.runner属性,因为Sync是私有类需要多反射一次 Field sync = FutureTask.class.getDeclaredField("sync"); sync.setAccessible(true); Object obj = sync.get(future); Field runner = obj.getClass().getDeclaredField("runner"); runner.setAccessible(true); // 获取到了执行该任务的线程 Thread execThread = (Thread) runner.get(obj); if (execThread == null) { return; } State state = execThread.getState(); if (state == State.RUNNABLE) { execThread.stop();// 非阻塞线程才STOP,例如死循环 } else { // 其他情况使用interrupt()方式,例如sleep、wait等等 } future.cancel(true); } catch (Exception e) { e.printStackTrace(); } }
完整Class:
/** * * 安全线程池,一个线程超时timeOut时间就杀掉这个线程。保证整个服务的稳定 */ public class SafeExecutorService extends ScheduledThreadPoolExecutor { Logger logger = LoggerFactory.getLogger(SafeExecutorService.class); public SafeExecutorService(int corePoolSize) { super(corePoolSize); } long timeOut = 5;// 超时时间 TimeUnit timeUnit = TimeUnit.MINUTES; ScheduledExecutorService timer = Executors .newSingleThreadScheduledExecutor(); public SafeExecutorService(int corePoolSize, long timeOut, TimeUnit timeUnit) { super(corePoolSize); this.timeOut = timeOut; this.timeUnit = timeUnit; } @Override public Future<?> submit(Runnable task) { final FutureTask<?> future = (FutureTask<?>) super.submit(task); timer.schedule(new Runnable() { @Override public void run() { killThread(future); } }, timeOut, timeUnit); return future; } /** * * 真正的终止任务 */ public void killThread(FutureTask<?> future) { try { if (future.isDone()) { return; } // 处理长时间超时的线程 // 利用反射,强行取出正在运行该任务的线程 // Thread属性藏在FutureTask.Sync.runner属性,因为Sync是私有类需要多反射一次 Field sync = FutureTask.class.getDeclaredField("sync"); sync.setAccessible(true); Object obj = sync.get(future); Field runner = obj.getClass().getDeclaredField("runner"); runner.setAccessible(true); // 获取到了执行该任务的线程 Thread execThread = (Thread) runner.get(obj); if (execThread == null) { return; } State state = execThread.getState(); if (state == State.RUNNABLE) { execThread.stop();// 非阻塞线程才STOP,例如死循环 } else { // 其他情况使用interrupt()方式,例如sleep、wait等等 } future.cancel(true); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { SafeExecutorService sss = new SafeExecutorService(2, 1, TimeUnit.SECONDS); sss.submit(new Runnable() { @Override public void run() { while (true) { System.out.println(1); } } }); sss.submit(new Runnable() { @Override public void run() { try { Thread.sleep(1000 * 500); } catch (InterruptedException e) { e.printStackTrace(); } } }); } }
简单的介绍一下就是在执行一个任务的时候开计时器,时间到了就判断这个任务是否已经完成。
没完成的就肯定是有问题的,需要杀掉这个任务防止影响整个服务。
这种做法可以用在系统的构建上,来确保不会因为业务影响所有的服务。
相关推荐
主要介绍了Java中一个线程执行死循环有什么后果,当一个线程在执行死循环时会影响另外一个线程吗,下面为大家揭晓
操作系统课程设计报告:实验三 Pintos线程管理【Pintos Project 1: Threads】
操作系统课程设计:实验三 Pintos线程管理【Pintos Project 1: Threads】
Android多线程任务优化2:实现后台预读线程
操作系统大作业:基于C++采用线程思想实现电梯调度程序
C++毕业设计:基于Qt的多线程局域网聊天系统(含客户端+服务端).zip C++毕业设计:基于Qt的多线程局域网聊天系统(含客户端+服务端).zip C++毕业设计:基于Qt的多线程局域网聊天系统(含客户端+服务端).zip C++...
操作系统 :多线程 CPU scheduling. 其中有FIFO, Round Robin
跨平台 linux 、windows实现原理功能状态实现原理list实现中双向循环链表rfifo基本实现环形队列queue实现中普通的队列构建方式构建该项目需要gcc版本>=4.6 主要原因是该项目中使用了内存屏障实现lock free注意:这个...
编写简单的HTTP 1.0客户端/服务器程序:.编写多线程Web服务器:编写简单的RMI程序 包含实验PPT 实验报告
重大软院操作系统实验二:线程调度,计算机操作系统原理,linux
1、通过本次试验掌握windows进程、线程的概念 2、理解创建和销毁windows进程、线程的过程 进程概念及其应用 线程概念及其应用 实验一 在windows下编写一个控制台应用程序,命名an_ch2_1b。这个程序不断地输出如...
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-...
qt 多线程 防止主线程做循环操作导致界面假死。试过多线程的几种方法,只有这个方法可行。代码亲测可行。在子线程死循环,界面正常不死!!!
Those output come from child,[系统时间] 另外写一个控制台应用程序,命名为an_ch2_1a。这个程序创建一个子进程,执行an_ch2_1b。这个程序不断地输出如下行: Those output come from child,[系统时间] 观察程序...
OH操作系统基础:Thread多线程
(1)掌握Windows系统提供的线程创建与撤销系统调用 (2)掌握Windows系统环境下线程的创建与撤销方法 2 实验准备知识 (1)线程创建 CreateThread()完成线程的创建。它在调用进程的地址空间上创建一个线程,执行...
操作系统原理:Chapter 4 线程.ppt
libpcap-MT:一种多线程的通用数据包捕获库
操作系统实验 线程的同步 深入理解线程与进程的概念,在Windows环境下何时使用进程,何时使用线程?
操作系统实验(三)线程的互斥 操作系统实验(三)线程的互斥