文档章节

线程中断以及线程中断引发的那些问题

一个程序员的成长
 一个程序员的成长
发布于 09/10 10:26
字数 1699
阅读 1143
收藏 29

上周写了一篇多线程的文章,其实更多方面是偏基础一点的文章,而且也比较大白话,争取人人都能看的明白,再举一些常见的例子,能很好的帮助大家理解多线程,文章发表之后我投给了几个大号和CSDN反应都挺好的,大家表示希望能写更多这样的文章,希望再多写写线程相关的文章,所以我打算从线程的基础开始写起,每周写那么两三篇,大家闲的时候可以看看,也可以多吸收一点东西。

另外,希望大家在阅读完之后能来个互动点赞什么的,也让我有点创作的动力,另外说说你们的想法什么的,我也好写出更好的文章来,废话不多说了,我们开始今天的知识点学习吧!

什么是线程中断?

在我们的Java程序中其实有不止一条执行线程,只有当所有的线程都运行结束的时候,这个Java程序才算运行结束。 官方的话给你描述一下:当所有的非守护线程运行结束时,或者其中一个线程调用了System.exit()方法时,这个Java程序才能运行结束。

线程中断的应用场景

我们先来举一个例子,比如我们现在在下载一个500多M的大片,我们点击开始下载,那个这个时候就等于开启了一个线程去下载我们的文件,然而这个时候我们的网速不是很给力,几十KB的在这跑,作为一个年轻人我是等不了了,我不下来,那么这个时候我们第一个操作就是结束掉这个下载文件的操作,其实更接近程序的来说,这个时候我们就需要把这个线程给中断了。

我们接下来写一下这个下载的代码,看一下如何中断一个线程,这里我已经默认你们已经掌握了如何创建一个线程了,这段程序我们模拟下载,最开始获取系统时间,然后进入循环每次获取系统时间,如果时间超过10秒我们就中断线程,不在继续下载,下载速度时每秒1M: 

public void run() {

       int number = 0;

       // 记录程序开始的时间
       Long start = System.currentTimeMillis();

       while (true) {

           // 每次执行一次结束的时间
           Long end = System.currentTimeMillis();

           // 获取时间差
           Long interval = end - start;

           // 如果时间超过了10秒,那么我们就结束下载
           if (interval >= 10000) {
               // 中断线程
               interrupted();
               System.err.println("太慢了,我不下了");
               return;
           } else if (number >= 500) {
               System.out.println("文件下载完成");
               // 中断线程
               interrupted();
               return;
           }

           number++;
           System.out.println("已下载" + number + "M");

           try {
               Thread.sleep(2000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }

中断线程的方式

Thread类中给我们提供了中断线程的方法,我们先来看下这个方法到底是如何让线程中断的:

public static boolean interrupted() {
       return currentThread().isInterrupted(true);
   }

这个方法是检查当前线程是否被中断,中断返回true,未中断返回false 

private native boolean isInterrupted(boolean ClearInterrupted);

通过查看源码我们可以发现,中断线程就是通过调用检查线程是否被中断的方法,把值设为true。这个时候你再去调用检查线程是否中断的方法时就返回true了。

这里大家需要注意一个问题:Thread.interrupted()方法只是修改了当前线程的状态告诉他被中断了,但是对于非阻塞中的线程,只是改变了中断状态,即 Thread.isInterrupted()返回true,对于可取消的阻塞状态中的线程,例如等待在这些函数上的线程 ,Thread.sleep(),这个线程收到中断信号之后就会抛出InterruptedException异常,同时会把中断状态设置为true。

线程睡眠引起InterruptedException异常的原因

其实这样说大家也是一知半解,我就写一个错误的示例,大家来看一下,把这个问题彻底的搞清楚:

public void run() {

       int number = 0;

       while (true) {
           // 检查线程是否被中断,中断就停止下载
           if (isInterrupted()) {

               System.err.println("太慢了,我不下了");
               return;
           } else if (number >= 500) {
               System.out.println("下载完成");
               return;
           }

           number++;
           System.out.println("已下载" + number + "M");

           try {
               Thread.sleep(2000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }

这是我们的主程序,等待10秒后中断线程

public static void main(String[] args) throws InterruptedException {

       Thread thread = new PrimeGenerator();

       // 启动线程
       thread.start();

       // 等待10秒后中断线程
       Thread.sleep(1000);

       // 中断线程
       thread.interrupt();
   }

看起来很通常的一个程序,但是事实却并非你看到的样子,其实这段代码是会抛出InterruptedException异常的,我们来分析原因。

这里我们先要了解Thread.interrupt()方法不会中断一个正在运行的线程,调用Thread.sleep()方法时,这个时候就不再占用CPU,我们来分析下我们这个程序,我们下载是要等待10秒,每次下载的速度是0.5M/S,也就是当我们下载到5M的时候等待时间已经到了,这个时候调用Thread.interrupt()方法中断线程,但是run()方法中的睡眠还要接着往下执行,它是不会因为中断而放弃执行下面的代码的,那么这个时候当它再执行Thread.sleep()的时候就会抛出InterruptedException异常,因为当前的线程已经被中断了。

说到这里,你是否已经明白产生这个异常的原因了?另外还有另外的两个原因致使线程产生InterruptedException异常的原因,wait()、join()两个方法使用不当也会引起线程抛出该异常。

查看线程是否中断的两种方式

在Thread类中有一个方法interrupted()可以用来检查当前线程时候被中断,还有isInterrupted()方法可以用来检查当前线程是否被中断。

中断线程的方法其实底层就是将这个属性设置为true,isInterrupted()方法只是返回了这个属性值而已。

这两个方法有一个区别就是isInterrupted()不能改变interrupted()的属性值,但是interrupted()方法却能改变interrupted的属性值,所以在判断一个线程时候被中断的时候我们更推荐使用isInterrupted()。

© 著作权归作者所有

共有 人打赏支持
一个程序员的成长
粉丝 19
博文 3
码字总数 6615
作品 0
西安
后端工程师
加载中

评论(2)

trivia
trivia

引用来自“trivia”的评论

`中断线程的方法其实底层就是将这个属性设置为true,isInterrupted()方法只是返回了这个属性值而已。`
这句话在我看了源码的注释后,我觉得和注释描述不太一样。

public static boolean interrupted() 这个静态方法调用的依然是实例方法private native boolean isInterrupted(boolean ClearInterrupted),静态方法调用native方法时将参数设置为true,参数的含义是是否清除此线程的中断状态
静态方法注释讲:
此方法检测当前线程是否已经被中断。当前线程的中断状态将被此方法清除。换句话说,如果这个方法被调用两次,则第二次调用时会返回false(除非这个线程在第一次调用这个静态方法清除中断状态后,并且在第二次调用之前,再次被中断)
另一个实例方法public boolean isInterrupted(),则不会清除线程中断状态,只是简单返回中断状态
trivia
trivia
`中断线程的方法其实底层就是将这个属性设置为true,isInterrupted()方法只是返回了这个属性值而已。`
这句话在我看了源码的注释后,我觉得和注释描述不太一样。

public static boolean interrupted() 这个静态方法调用的依然是实例方法private native boolean isInterrupted(boolean ClearInterrupted),静态方法调用native方法时将参数设置为true,参数的含义是是否清除此线程的中断状态
静态方法注释讲:
此方法检测当前线程是否已经被中断。当前线程的中断状态将被此方法清除。换句话说,如果这个方法被调用两次,则第二次调用时会返回false(除非这个线程在第一次调用这个静态方法清除中断状态后,并且在第二次调用之前,再次被中断)
多线程编程读书笔记之线程中断的本质

Java试图提供过抢占式限制中断,但问题多多,例如已被废弃的Thread.stop、Thread.suspend和 Thread.resume等。另一方面,出于Java应用代码的健壮性的考虑,降低了编程门槛,减少不清楚底层机...

刘学炜
2012/07/03
0
0
JUC系列四:任务的取消与关闭

在大多数情况下,我们创建一个任务,都会让它运行直到结束。但有时,又需要在某种情况下取消任务,比如用户请求取消,有时间限制的任务,任务运行时出现错误等等。在Java中,没有一种安全的抢...

那位先生
2015/08/09
0
0
JAVA多线程之中断机制(如何处理中断?)

一,介绍 这篇文章主要记录使用 interrupt() 方法中断线程,以及如何对InterruptedException进行处理。感觉对InterruptedException异常进行处理是一件谨慎且有技巧的活儿。 由于使用stop()方...

lwang_IT
2017/12/04
0
0
Java编程的逻辑 -- 并发章 -- 线程的中断

线程中断 线程不同状态对中断的反应 总结 线程中断 在Java中,停止一个线程的主要机制是中断,中断并不是强迫终止一个线程,它是一种协作机制,是给线程传递一个取消信号,但是由线程来决定如...

HikariCP
06/25
0
0
关闭线程的正确方法:“优雅”的中断

前文从任务到线程:Java结构化并发应用程序中介绍了如何安排任务启动线程。 线程在启动之后,正常的情况下会运行到任务完成,但是有的情况下会需要提前结束任务,如用户取消操作等。可是,让...

登高且赋
2017/10/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spark Load Data and Export Data

Load_Data_Command 一、导入数据-加载csv文件数据作为spark 临时表DataSource(不需要提前创建表,方便数据分析) 该命令将csv文件导入到临时表中,命令格式为 load data '文件路径' table [...

Avner
22分钟前
2
0
CDH5.13离线安装Spark2.3详细步骤

简介: 在我的CDH5.13集群中,默认安装的spark是1.6版本,这里需要将其升级为spark2.x版本。经查阅官方文档,发现spark1.6和2.x是可以并行安装的,也就是说可以不用删除默认的1.6版本,可以直...

hblt-j
26分钟前
2
0
Add XSS protection headers on Nginx

Add XSS protection headers on Nginx Add the following line in the http or server part of your Nginx configuration : ... # XSS Protection add_header X-Frame-Opt......

idoz
26分钟前
1
0
cmake windows 配置xp toolset

MPRO
33分钟前
2
0
day125-20181023-英语流利阅读-待学习

外卖员不要哭,打零工不容易 雪梨 2018-10-23 1.今日导读 上期我们讲到,有人认为:“零工经济”虽然没有占领全世界,但它剥夺了劳动者的合法权利,加剧了工作的不稳定性,那么“零工经济”是...

飞鱼说编程
45分钟前
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部