Thread中断简单介绍

Android2024年8月1日 pm6:45发布2个月前更新 91es.com站长
68 0 0
目录

前言

简答记录一下Thread中断相关的内容。

记录一下,方便自己查阅。

正文

Thread中断主要涉及如下几个方法:

  1. interrupt()

  2. isInterrupted()

  3. interrupted()

下面单独介绍一下。

interrupt()

interrupt()使线程中断。

重点:当线程调用interrupt()时,仅仅设置中断标志位true,此时线程是不会被中断的,会一直执行直到结束。

为了让人易懂,简单测试一下。

测试一

先定义一个MyThread类(比较简单,只是为了测试而已)

private class MyThread extends Thread {
    public MyThread(String name) {
        setName(name);
    }

    @Override
    public void run() {
        super.run();
        Log.d(TAG, "run thread name : " + getName() + " start ");
        for (int i = 0; i < 1000; i++) {
            Log.d(TAG, "run thread name : " + getName() + " [ " + i + " ] ");
        }
        Log.d(TAG, "run thread name : " + getName() + " end , isInterrupted() : " + isInterrupted());
    }
}
MyThread myThreadA = new MyThread("Thread_A");
myThreadA.start();
try {
    Thread.sleep(10);
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}
Log.d(TAG, "myThreadA.interrupt() : ");
myThreadA.interrupt();

下面打印日志:

// ...为省略,打印太多了。
run thread name : Thread_A start
...
run thread name : Thread_A [ 102 ]
...
myThreadA.interrupt() 
...
run thread name : Thread_A [ 999 ] 
run thread name : Thread_A end , isInterrupted() : true

从上面可以看出,调用interrupt()后,并不会终止线程中断,直到线程for循环结束,最后打印时中断标志位以为true。

  1. interrupt()会改变中断标志位位true

  2. interrupt()不会打断Thread执行任务,直到自动结束。

测试二

当然,如果线程调用了wait方法、join方法或者sleep方法而被阻塞挂起,此时如果线程A的interrupt(),线程会在调用这些方法的地方抛出InterruptedException异常而返回。

下面我们在ThreadA中的for循环中添加sleep(),其他的保持不变。

private class MyThread extends Thread {
    public MyThread(String name) {
        setName(name);
    }

    @Override
    public void run() {
        super.run();
        Log.d(TAG, "run thread name : " + getName() + " start ");
        for (int i = 0; i < 1000; i++) {
            Log.d(TAG, "run thread name : " + getName() + " [ " + i + " ] ");
            try {
                sleep(10);
            } catch (InterruptedException e) {
                Log.d(TAG, "run e: "+ e);
                break;//退出for循环
            }
        }
        Log.d(TAG, "run thread name : " + getName() + " end , isInterrupted() : " + isInterrupted());
    }
}

调用那部分不改变,这里省略,打印日志如下:

run thread name : Thread_A start 
run thread name : Thread_A [ 0 ] 
myThreadA.interrupt() 
run e: java.lang.InterruptedException
run thread name : Thread_A end , isInterrupted() : false

很快就在sleep()中收到InterruptedException,然后我们退出了for循环。

  1. interrupt() 时,如果有sleep()等代码,会抛出InterruptedException

  2. 在1(基础上)抛出异常后最后中断状态为false

也就是说出行InterruptedException后,会影响中断标志位。

由于对Thread源码不是很了解,在,有兴趣的可以看Thread相关的源码。

后续后续有空看一下,这里先插个眼!

isInterrupted()

检测当前线程是否被中断,如果是返回true,否则返回false。

下面测试一下,在ThreadA中新增isInterrupted()判断,如果为true,就结束for循环

private class MyThread extends Thread {
    public MyThread(String name) {
        setName(name);
    }

    @Override
    public void run() {
        super.run();
        Log.d(TAG, "run thread name : " + getName() + " start ");
        for (int i = 0; i < 1000; i++) {
            Log.d(TAG, "run thread name : " + getName() + " [ " + i + " ] ");
            if(isInterrupted()){
                Log.d(TAG, "run isInterrupted break: ");
                break;
            }
        }
        Log.d(TAG, "run thread name : " + getName() + " end , isInterrupted() : " + isInterrupted());
    }
}

其他的保持不变[跟interrupt()中代码一样,这里略],打印日志如下:

run thread name : Thread_A start 
run thread name : Thread_A [ 0 ] 
...
myThreadA.interrupt() : 
run thread name : Thread_A [ 100 ] 
run thread name : Thread_A [ 101 ] 
run isInterrupted break: 
run thread name : Thread_A end , isInterrupted() : true

执行中断后,isInterrupted()返回true,然后break退出循环。

  1. interrupt()时,isInterrupted()会返回true

  2. isInterrupted()返回结果后,不会改变中断标志,所以打印依旧为true

interrupted()

如果线程被中断,返回true,否则返回false。

如果interrupted()返回true后,会把中断标志位清除,置为false。

下面简单的测试一下。新增interrupted()判断,如果返回true,就break线程中的for选好

private class MyThread extends Thread {
    public MyThread(String name) {
        setName(name);
    }

    @Override
    public void run() {
        super.run();
        Log.d(TAG, "run thread name : " + getName() + " start ");
        for (int i = 0; i < 1000; i++) {
            Log.d(TAG, "run thread name : " + getName() + " [ " + i + " ] ");
            if(interrupted()){
                Log.d(TAG, "run interrupted break : ");
                break;
            }
        }
        Log.d(TAG, "run thread name : " + getName() + " end , isInterrupted() : " + isInterrupted());
    }
}

执行后日志打印。

run thread name : Thread_A start 
run thread name : Thread_A [ 0 ] 
...
myThreadA.interrupt() : 
run thread name : Thread_A [ 242 ] 
run interrupted break : 
run thread name : Thread_A end , isInterrupted() : false
  1. 调用interrupt()后,interrupted()返回true

  2. interrupted()执行后,把中断标志位置为false

小结

  1. interrupt()设置中断标志位,如果有sleep(),wait()等会抛出InterruptedException

  2. isInterrupted()判断中断标志位是否为true

  3. interrupted()判断中断标志位是否为true,如果当为true,把中断标志位清除(置为false)

  4. interrupted()是静态方法

至于深入Thread源码,暂时没空,先插个眼

参考文章

  1. 《Java并发编程之美》

 历史上的今天

  1. 2023: ViewPager禁止左右滚动(0条评论)
  2. 2022: Android GridView horizontalSpacing属性值无效(0条评论)
  3. 2021: 陈先发:前世(0条评论)
  4. 2019: 朱光潜:有趣的灵魂都有静气(0条评论)
版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com[备用域名]
3、 本站内容: 部分来源于网络,仅供站长学习和参考,若侵权请留言

暂无评论

暂无评论...

随机推荐

[摘]Android 系统重启原因分析

前言Android重启,这种影响使用的问题必须解决和找出原因。正文以下是摘抄文章内容,略有删减。重启原因分类上层造成重启system_server被杀watchdog重启重要线程阻塞kernel造成重启空指针非法地址kernel watchdog造成重启,...

无效的UTF-8字符串引发的问题

前言最近在调试多媒体时,出现特别奇怪的问题,也就是扫描磁盘中文件时被中断了,之前都是好的。记录于此,方便自己查阅。好记性不如烂笔头正文部分异常日志如下。 signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort...

自定义垂直Seekbar之添加事件监听

前言本文是《自定义垂直Seekbar简介》基础上进行修改的,参考Android原生的SeekBar的setOnSeekBarChangeListener新增的。后面新增的,重新开一片文章记录一下。正文本文跟《自定义垂直Seekbar简介》内容差不多,就是新增了setOnSeekBarCha...

adb shell top 命令的简单使用

前言top命令提供了实时的对Android系统处理器的状态监视.它将显示系统中CPU最“敏感”的任务列表.该命令可以按CPU使用.内存使用和执行时间对任务进行排序.adb shell top 的简介top 可以带参数等,具体下面详细简介top 用法使用adb shell top --he...

Unable to make field

前言升级新版本Android Studio后倒入部分工程出现如下问题:Unable to make field private final java.lang.String java.io.File.path accessible: module java.base does not "ope...

Android mk编译apk和拷贝apk

前言简单记录一下Android.mk编译apk和拷贝APK,这也是源码编译中常用的。这里只是简单记录一下,方便自己使用。正文直入正文,至于两者查阅,自己对比和查阅资料吧。编译apkLOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOC...