理解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线程中断

java中断的更多相关文章

  1. Java 中断异常的正确处理方式

    处理InterruptedException 这个故事可能很熟悉:你正在写一个测试程序,你需要暂停某个线程一段时间,所以你调用 Thread.sleep().然后编译器或 IDE 就会抱怨说 Inte ...

  2. java 中断线程的几种方式 interrupt()

    中断 中断(Interrupt)一个线程意味着在该线程完成任务之前停止其正在进行的一切,有效地中止其当前的操作.线程是死亡.还是等待新的任务或是继续运行至下一步,就取决于这个程序.虽然初次看来它可能显 ...

  3. 【Java多线程】Java 中断

    如何安全的结束一个正在运行的线程 java.lang.Thread类包含了一些常用的方法,如:start(), stop(), stop(Throwable) ,suspend(), destroy( ...

  4. Java中断异常 InterruptedException 的正确处理方式

    你看到这篇文件可能是因为你已经调用了一个抛出 InterruptedException 异常的方法,并且需要以某种方式处理它. 首先,需要了解为一个方法为啥会 throws InterruptedEx ...

  5. Java 中断

    https://zhuanlan.zhihu.com/p/45667127 看的似懂非懂

  6. Java 中断线程

  7. Java线程中断的本质深入理解(转)

    一.Java中断的现象 首先,看看Thread类里的几个方法: public static boolean interrupted 测试当前线程是否已经中断.线程的中断状态 由该方法清除.换句话说,如 ...

  8. java线程池和中断总结

    目录 java线程池和中断总结 一. 线程池的使用 二. java中断机制 中断的处理 三. 线程间通信机制总结 java线程池和中断总结 本系列文是对自己学习多线程和平时使用过程中的知识梳理,不适合 ...

  9. Java线程中断的本质深入理解

    Java的中断是一种协作机制.也就是说调用线程对象的interrupt方法并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时机中断自己. 一.Java中断的现象 首先,看看Thread类里的 ...

随机推荐

  1. hihoCoder 1288 Font Size 二分

    题意:给定一个宽度为和高度为的屏幕,如果字体的大小为,那么一行可以显示个字,每一页可以显示行.给出段文本段落,每段有个文字,问现在能设置的最大字体并且总的页数不能超过? 思路:如果知道字体大小很容易求 ...

  2. 用线性单元(LinearUnit)实现工资预测的Python3代码

    功能:通过样本进行训练,让线性单元自己找到(这就是所谓机器学习)工资计算的规律,然后用两组数据进行测试机器是否真的get到了其中的规律. 原文链接在文尾,文章中的代码为了演示起见,仅根据工作年限来预测 ...

  3. ios开发之自定义textView

    自定义textView,从理论上讲很简单,根据需求自定义,比如我在开发中的需求就是现实一个字数的限制以及根据输入的文字改变提示剩余字数,那么开始我的基本思路就是自定义一个View,而里面包含一个子控件 ...

  4. (1)常见O(n^2)排序算法解析

    一.选择排序 1.原始数组 2.遍历数组找到最小值索引,并将最小值索引与当前遍历索引位置互换 3.确定最小位置值,进行下一次遍历 4.java代码实现 /** * author:sam * date: ...

  5. 第5章 PCIe总线的事务层

    事务层是PCIe总线层次结构的最高层,该层次将接收PCIe设备核心层的数据请求,并将其转换为PCIe总线事务,PCIe总线使用的这些总线事务在TLP头中定义.PCIe总线继承了PCI/PCI-X总线的 ...

  6. spring-java项目中连接redis数据库

    最近由于项目需要,要从redis数据库中查询一些数据,还没有了解过redis,只好硬着头皮上阵,记录一下连接过程: 1.需要导入两个jar包:jedis.jar,spring-data-redis.j ...

  7. 利用PowerDesigner15在win7系统下对MySQL 进行反向工程(一)

    利用PowerDesigner15在win7系统下对MySQL 进行反向工程 1.首先,安装以下的驱动 2.找到"C:\Windows\System32" 3.双击"od ...

  8. Caused by: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'content' a

    1.错误描述 org.hibernate.exception.DataException: could not execute statement at org.hibernate.exception ...

  9. 芝麻HTTP: Python爬虫利器之PyQuery的用法

    前言 你是否觉得 XPath 的用法多少有点晦涩难记呢? 你是否觉得 BeautifulSoup 的语法多少有些悭吝难懂呢? 你是否甚至还在苦苦研究正则表达式却因为少些了一个点而抓狂呢? 你是否已经有 ...

  10. HTML5结合CSS的三种方法+结合JS的三种方法

    HTML5+CSS: HTML中应用CSS的三种方法 一.内联 内联样式通过style属性直接套进HTML中去. 示例代码 <pstylepstyle="color:red" ...