关闭

多线程中断机制

标签: 多线程中断机制interruptjava
10440人阅读 评论(17) 收藏 举报
分类:

友情推荐:

  1. 线程池原理
  2. 深入Thread.sleep
  3. head first Thread.join()

在 java中启动线程非常容易,大多数情况下是让一个线程执行完自己的任务然后自己停掉。一个线程在未正常结束之前, 被强制终止是很危险的事情. 因为它可能带来完全预料不到的严重后果,比如会带着自己所持有的锁而永远的休眠,迟迟不归还锁等。在当前的api中,Thread.suspend、Thread.stop等方法都被Deprecated了,线程只能用interrupt中断,而且不是立刻中断,只是发了一个类似于信号量的东西,通过修改了被调用线程的中断状态来告知那个线程, 说它被中断了,至于什么时候中断,这个有系统判断,会在一个合适的时候进行中断处理。

/**
 * Created by Zero on 2017/8/17.
 */
public class ThreadTest1 {
    public static void main(String[] args) {
        NThread nThread = new NThread();
        System.out.println("interrupt执行前");
        nThread.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        nThread.interrupt();
        System.out.println("interrupt执行后");
    }

    /**
     * 测试多线程的中断机制
     */
    static class NThread extends Thread{
        @Override
        public void run() {
            super.run();
            while(true){
                System.out.println("依然存活...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

这里写图片描述

在上面代码中,线程睡醒之后,调用thread线程的interrupt方法,catch到InteruptedException,设置标志位。interrupt()方法相当于线程睡着的时候一盆凉水来吵醒它,线程表示不开心,并向你抛出一个大大的异常以示不满。

这里写图片描述

  • 首先:线程中断是一种协作机制,调用线程对象的interrupt方法并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时间中断自己。
  • 其次:任务的方法必须是可中断的,即方法必须抛出InterruptedException。

由此可见,interrupt() 方法并不能立即中断线程,该方法仅仅告诉线程外部已经有中断请求,至于是否中断还取决于线程自己。在Thread类中除了interrupt() 方法还有另外两个非常相似的方法:interrupted 和 isInterrupted 方法,下面来对这几个方法进行说明:

  • interrupt 此方法是实例方法,用于告诉此线程外部有中断请求,并且将线程中的中断标记设置为true,而不是立即中断。
  • interrupted 此方法是类方法,用来判断当前线程是否已经中断。线程的中断状态由该方法清除。
  • isInterrupted 此方法是实例方法,用来判断线程是否已经中断。线程的中断状态不受该方法的影响。

总结:java线程中断机制通过调用Thread.interrupt() 方法来做的,这个方法通过修改了被调用线程的中断状态来告知那个线程说它被中断了。对于非阻塞中的线程,只是改变了中断状态,即Thread.isInterrupted() 将返回true;对于可取消的阻塞状态中的线程,比如等待在这些函数上的线程,Thread.sleep()、Object.wait()、Thread.join(), 这个线程收到中断信号后,会抛出InterruptedException,同时会把中断状态置回为true。但调用Thread.interrupted()会对中断状态进行复位。

/**
 * Created by Zero on 2017/8/17.
 */
public class ThreadTest1 {
    public static void main(String[] args) {
        NThread nThread = new NThread();
        nThread.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("cancel执行前" + System.currentTimeMillis());
        nThread.cancel();
    }

    /**
     * 测试多线程的中断机制
     */
    static class NThread extends Thread {

        private boolean isCancel;

        @Override
        public void run() {
            while (!isCancel) {
                System.out.println("依然存活...");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
            }
            System.out.println("while结束" + System.currentTimeMillis());
        }

        public void cancel() {
            this.isCancel = true;
        }
    }
}

执行结果:

依然存活...
cancel执行前1502964413042
while结束1502964415042

机智的你,此刻一定发现执行前后相差2000毫秒,难道cancel()方法执行了2000毫秒?这纯属扯淡,里面没有任何耗时操作,就是一个赋值而已,其实是子线程的退出,前提条件是while循环结束,当且仅当cancel标示设置为true的瞬间立马执行while的判断,此时的时间差才可以忽略不计(1毫秒内),但是当我们调用cancel方法将isCancel 标记设置为true 时,while循环里面有一个耗时操作(休眠5000毫秒),只有等待耗时操作执行完毕后才会去检查这个标记,所以cancel方法和线程退出中间有时间间隔。

接下来,我们通过interrupt 和 isinterrupt 方法来中断线程,代码如下:

/**
 * Created by Zero on 2017/8/17.
 */
public class ThreadTest1 {
    public static void main(String[] args) {
        NThread nThread = new NThread();
        nThread.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("interrupt执行前"+System.currentTimeMillis());
        nThread.interrupt();
    }

    /**
     * 测试多线程的中断机制
     */
    static class NThread extends Thread{

        @Override
        public void run() {
            while(!interrupted()){
                System.out.println("依然存活...");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    System.out.println("InterruptedException");
                    Thread.currentThread().interrupt();
                }
            }
            System.out.println("interrupt执行后"+System.currentTimeMillis());
        }
    }
}
依然存活...
interrupt执行前1502965915683
InterruptedException
interrupt执行后1502965915683

这次立马中断了,是因为在开启子线程后,经过执行3000毫秒的休眠,线程执行了interrupt 方法,此时子线程的5000毫秒休眠还没结束,就像上述所说的睡眠中被一盆冷水吵醒,很不开心的抛了异常,Thread.currentThread().interrupt() 改变了线程的标记状态,在抛出InterruptedException 的同时,线程的中断标志被清除了,再次执行while循环语句的时候,!interrupted() 此时是false,便不再执行while语句。

此处如果去掉Thread.currentThread().interrupt() ,线程便会无休止的执行下去,此处就不上代码了,就注释掉这一行,运行就可以看到效果,经常看到一些代码在catch中不作任何处理,其实有时候这样是很危险的,此处已经证明。

两点建议:
1. 除非你知道线程的中断策略,否则不应该中断它。
2. 任务代码不该猜测中断对执行线程的含义。遇到InterruptedException异常时,不应该将其捕获后“吞掉”,而应该继续向上层代码抛出。

微信扫我,^_^

5
0
查看评论

操作系统的中断机制

CPU进行进程之间的切换以及可以处理多个任务都是通过中断请求来实现的。在计算机系统中每个硬件组建都有各自唯一的一个中断请求装置,例如键盘键盘的中断装置,鼠标有鼠标的中断装置,那键盘来说,当按下某个按键时候,就会出发键盘的中断装置,发出中断请求,核心就是发出一个脉冲信号(从这里可以明白,计算机一切的执...
  • liliangbing123
  • liliangbing123
  • 2014-01-19 03:19
  • 1975

深入分析Java线程中断机制

在平时的开发过程中,相信都会使用到多线程,在使用多线程时,相信大家也会遇到各种各样的问题,今天我们就来说说一个多线程的问题——线程中断。在java中启动线程非常容易,大多数情况下我是让一个线程执行完自己的任务然后自己停掉,但是有时候我们需要取消某个操作,比如你在网络下载时,有时候需要取消下载。实现线...
  • yuanzeyao2008
  • yuanzeyao2008
  • 2015-08-01 15:04
  • 3817

Linux内核——中断机制

中断机制 为什么需要中断? 如果让内核定期对设备进行轮询,以便处理设备,那会做很多无用功,因为外设的处理速度一般慢于CPU,而CPU不能一直等待外部事件。所以能让设备在需要内核时主动通知内核,会是一个聪明的方式,这便是中断。 中断处理程序 在响应一个特定中断时,内核会执行一个函数——中断处理程序。中...
  • walkerkalr
  • walkerkalr
  • 2014-08-06 13:57
  • 1540

【多线程_提高】 Java中断机制

1. 引言 当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时……都需要通过一个线程去取消另一个线程正在执行的任务。Java没有提供一种安全直接的方法来停止某个线程,但是Java提供了中断机制。 如果对Java中断没有一个全面的了解,可能会误以为...
  • kingzma
  • kingzma
  • 2015-04-28 15:04
  • 285

Java多线程17:中断机制

概述 之前讲解Thread类中方法的时候,interrupt()、interrupted()、isInterrupted()三个方法没有讲得很清楚,只是提了一下。现在把这三个方法同一放到这里来讲,因为这三个方法都涉及到多线程的一个知识点----中断机制。 Java没有提供一种安全、直接的...
  • tianya3530
  • tianya3530
  • 2017-01-03 11:31
  • 302

16位/32位中断机制比较

16位/32位中断机制比较 原理: 16位中断机制:使用中断向量表 32位中断机制:使用中段描述符表IDT 位置: 中断向量表的位置是固定的,位于内存的开始0x00000 中断向量符表位置不固定,由系统设计者安排,由IDTR(IDT基地址寄存器)锁定其位置。
  • luoyhang003
  • luoyhang003
  • 2014-07-09 00:20
  • 1369

中断机制

中断分为非屏蔽中断和屏蔽中断。异常又分为故障和陷阱。    异常的向量和非屏蔽中断的向量和是固定的,而屏蔽中断的向量可以通过对中断控制器的编程来改变。Linux对256个向量的分配如下:    1、从0~31的向量对应于异常和非屏蔽中断。  ...
  • jltxgcy
  • jltxgcy
  • 2015-02-09 15:32
  • 865

linux内核架构-中断处理机制

本文对中断系统进行了全面的分析与探讨,主要包括中断控制器、中断分类、中断亲和力、中断线程化与 SMP 中的中断迁徙等。首先对中断工作原理进行了简要分析,接着详细探讨了中断亲和力的实现原理,最后对中断线程化与非线程化中断之间的实现机理进行了对比分析。 1 什么是中断? Linux 内核需要对连接到...
  • shenwanjiang111
  • shenwanjiang111
  • 2015-08-26 13:18
  • 1117

ARM中断机制

ARM中断机制 当事件发生时,通过一种机制告诉CPU现在发生什么事件,CPU停下现在所做的工作进行处理。中断处理流程:中断控制器汇集各类外设发出的中断信号,经过一段处理,选出一个信号,然后通知CPU;CPU保存当前运行环境,然后调用中断服务程序(ISR)处理中断;在ISR中通过读取相关寄存器的外设...
  • A3203211
  • A3203211
  • 2014-03-04 21:53
  • 1068

Linux内核的中断机制

根据中断来源分为:内部中断(来自于CPU内部,如中断指令、溢出等)和外部中断(来自于外设,如读写完成中断) 根据是都可屏蔽分成:可屏蔽中断和不屏蔽中断(NMI),可屏蔽中断通过中断屏蔽字被屏蔽,屏蔽后,该中断不再的导向响应;不屏蔽中断不能被屏蔽。 根据中断入口跳转方法的不同,分成向量中断和非向量中断...
  • smallfish_love
  • smallfish_love
  • 2016-02-28 14:50
  • 928
    个人资料
    • 访问:263112次
    • 积分:2991
    • 等级:
    • 排名:第13885名
    • 原创:46篇
    • 转载:0篇
    • 译文:0篇
    • 评论:329条
    QQ交流群

    Android路上

    611566797
    博客专栏
    我的公众号