java中断
理解java中断
Java中断机制是一种协作机制,即通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理中断。例如,当线程t1想中断线程t2,只需要在线程t1中将线程t2对象的中断标识置为true,然后线程2可以选择在合适的时候处理该中断请求,甚至可以不理会该请求,就像这个线程没有被中断一样。
中断相关的方法:
public class Thread{
public void interrupt(){} //中断目标线程,实际上就是设置中断状态为true
public boolean isInterrupted(){} //返回目标线程的中断状态
public static boolean interrupted(){} //清除当前线程的中断状态,并返回它之前的值
}
非静态方法和静态方法的区别:
//调用native方法,判断线程是否被中断,不清除中断状态
public boolean isInterrupted() {
return isInterrupted(false);
}
//调用native方法,判断线程是否被中断,清除中断状态
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
//native方法,测试线程是否被中断。ClearInterrupted决定是否需要清除中断状态
private native boolean isInterrupted(boolean ClearInterrupted);
JVM内部确实为每个线程维护了一个中断标记。但应用程序不能直接访问这个中断变量,必须通过上面几个方法进行操作。通常情况下,调用线程的interrupt方法,并不能立即引发中断,只是设置了JVM内部的中断标记。因此,通过检查中断标记,应用程序可以做一些特殊操作,也可以完全忽略中断。
哪些场景可以用到中断?
- 如果一个方法声明抛出InterruptedException,表示该方法是可中断的。比如sleep、wait、join等。
//Thread类,native方法,当前线程休眠mills毫秒。如果其他线程中断当前线程,则当前线程抛出异常InterruptedException的时候清除当前线程的中断状态。
public static native void sleep(long millis) throws InterruptedException;
//Object类
public final native void wait(long timeout) throws InterruptedException;
public final native void notify();
public final native void notifyAll();
- 自定义的可中断方法。需要在适合处理中断的地方检测线程中断状态并处理。
if(Thread.currentThread().isInterrupted()){
//do something
}
阻塞方法怎么响应中断
- 对于自定义的可中断的方法,如上,在必要的时候,判断线程中断状态,来响应中断。当然,如果执行的时候,一直没有判断中断状态,自然也不会响应中断。
- java封装的可中断方法,sleep等,是由JVM来控制的。
一些不会抛出 InterruptedException 的线程阻塞操作
然而,对于某些线程阻塞操作,JVM并不会自动抛出InterruptedException异常。例如,某些I/O操作和内部锁操作。对于这类操作,可以用其他方式模拟中断:
- java.io中的同步IO
读写socket的时候,InputStream和OutputStream的read和write方法会阻塞等待,但不会响应java中断。不过,调用Socket的close方法后,被阻塞线程会抛出SocketException异常。 - 利用Selector实现的异步I/O
如果线程被阻塞于Selector.select(在java.nio.channels中),调用wakeup方法会引起ClosedSelectorException异常。 - 等待获取某个内置锁
如果线程在等待获取一个内部锁,我们将无法中断它。但是,利用Lock类的lockInterruptibly方法,我们可以在等待锁的同时,提供中断能力。
实战
考虑以下场景,使用线程池执行任务,任务包含一系列查询操作和一个修改操作,查询操作可能超时。每个任务的超时时间是3秒。如果FutureTask超时返回,而任务还在继续执行,就会造成数据不一致。这时候需要再查询一次任务的结果才知道执行是否成功。而如果超时之后直接查询,有可能任务还在执行中,这时查到的也是不一样的。此时,可以任务外超时处理中,取消任务;同时,任务内在合适的部分,添加是否中断的判断。如:
//任务外超时处理中,取消任务
try{
SaveResult result = task.get(3000, TimeUnit.MILLISECONDS)); //3s超时
}catch (Exception e){
if(e instanceof TimeoutException){
//超时返回,不知道结果,需要取消任务;参数true表示中断正在执行的操作
task.cancel(true);
}
}
//任务内在合适的部分,添加中断的判断和相关操作
Future<SaveResult> task = executor.submit(new Callable<SaveResult>() {
@Override
public SaveResult call() throws Exception {
//do something, 1.5s
//do others, 1.5s
//任务内,判断当前线程是否被中断,如果已经被中断,则不执行变更操作
if(!Thread.currentThread.isInterruptrf()){
//update sth
}
return result ;
}
});
看看FutureTask中cancel源码,如果需要中断,则是使用线程中断的方式
public boolean cancel(boolean mayInterruptIfRunning) {
if (state != NEW)
return false;
if (mayInterruptIfRunning) {
if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING))
return false;
Thread t = runner;
if (t != null)
t.interrupt();
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state
}
else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED))
return false;
finishCompletion();
return true;
}
参考
java中断的更多相关文章
- Java 中断异常的正确处理方式
处理InterruptedException 这个故事可能很熟悉:你正在写一个测试程序,你需要暂停某个线程一段时间,所以你调用 Thread.sleep().然后编译器或 IDE 就会抱怨说 Inte ...
- java 中断线程的几种方式 interrupt()
中断 中断(Interrupt)一个线程意味着在该线程完成任务之前停止其正在进行的一切,有效地中止其当前的操作.线程是死亡.还是等待新的任务或是继续运行至下一步,就取决于这个程序.虽然初次看来它可能显 ...
- 【Java多线程】Java 中断
如何安全的结束一个正在运行的线程 java.lang.Thread类包含了一些常用的方法,如:start(), stop(), stop(Throwable) ,suspend(), destroy( ...
- Java中断异常 InterruptedException 的正确处理方式
你看到这篇文件可能是因为你已经调用了一个抛出 InterruptedException 异常的方法,并且需要以某种方式处理它. 首先,需要了解为一个方法为啥会 throws InterruptedEx ...
- Java 中断
https://zhuanlan.zhihu.com/p/45667127 看的似懂非懂
- Java 中断线程
- Java线程中断的本质深入理解(转)
一.Java中断的现象 首先,看看Thread类里的几个方法: public static boolean interrupted 测试当前线程是否已经中断.线程的中断状态 由该方法清除.换句话说,如 ...
- java线程池和中断总结
目录 java线程池和中断总结 一. 线程池的使用 二. java中断机制 中断的处理 三. 线程间通信机制总结 java线程池和中断总结 本系列文是对自己学习多线程和平时使用过程中的知识梳理,不适合 ...
- Java线程中断的本质深入理解
Java的中断是一种协作机制.也就是说调用线程对象的interrupt方法并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时机中断自己. 一.Java中断的现象 首先,看看Thread类里的 ...
随机推荐
- 一、Python介绍
Python 是一门什么样的语言? python是一门动态解释性的强类型定义语言. 编程语言主要从以下几个角度为进行分类,编译型和解释型.静态语言和动态语言.强类型定义语言和弱类型定义语言,每个分类代 ...
- CodeForces - 551C 二分+贪心
题意:有n个箱子形成的堆,现在有m个学生,每个学生每一秒可以有两种操作: 1: 向右移动一格 2: 移除当前位置的一个箱子 求移除所有箱子需要的最短时间.注意:所有学生可以同时行动. 思路:二分时间, ...
- 在SpringBoot中配置定时任务
前言 之前在spring中使用过定时任务,使用注解的方式配置很方便,在SpringBoot中的配置基本相同,只是原来在spring中的xml文件的一些配置需要改变,在SpringBoot中也非常简单. ...
- 20170109| javascript记录
1.时间戳的使用: 在php中的时间戳是以秒为单位的,在js中转换过来的时间戳是以毫秒为单位的.当我们使用js和php同时开发的时候,就需要保证它们都是处于同一时间单位下才好进行相关的计算. 首先说一 ...
- (转载)windows下mysql忘记密码
Mysql版本:5.1 1. 首先检查mysql服务是否启动,若已启动则先将其停止服务,可在开始菜单的运行,使用命令: net stop mysql 打开第一个cmd窗口,切换到mysql的bin目录 ...
- MSQL的基准测试
Mysql基准测试 基准测试 直接.简单.易于比较,用于评估服务器的处理能力 压力测试 对真实的月数据进行测试,获得真是系统所能承受的压力 基准测试的目的 1.建立MySQL服务器的性能基准线 2.模 ...
- localhost直接访问子文件夹无法完成
刚装上新版的wamp,之前的改动都初始化了,发现了一个问题,localhost不能直接访问子文件夹了,从网上找了找答案,没费事,解决了. 将WWW目录下的index.php打开,更改里面的内容,更改内 ...
- wpf通过VisualTreeHelper找到控件内所有CheckBox和TextBox并做相应绑定
#region CheckBox与TextBox绑定 Dictionary<CheckBox, TextBox> CheckTextBoxDic = new Dictionary<C ...
- Android开发学习必备的java知识
Android开发学习必备的java知识本讲内容:对象.标识符.关键字.变量.常量.字面值.基本数据类型.整数.浮点数.布尔型.字符型.赋值.注释 Java作为一门语言,必然有他的语法规则.学习编程语 ...
- window下如何使用Git上传代码到github远程服务器上(转)
注册账户以及创建仓库 首先你得有一个github账号,没有自行注册,登录成功后应该是这样 在页面上方用户菜单上选择 "+"->New repository 创建一个新的仓库 ...