中断机制-interrupt和isInterrupted源码分析、中断协商案例

Java线程中断并不立即停止,而是设置中断标志。在正常活动状态下,interrupt只改变标志,线程继续运行。若线程阻塞(如sleep, wait, join),interrupt会使其抛InterruptedException并清除中断状态。Thread.interrupted()会清除中断状态,而isInterrupted()则不会。" 58261751,5857731,解决MySQL导出Excel乱码问题,"['MySQL', 'java', 'excel', '服务器']
摘要由CSDN通过智能技术生成

当前线程的中断标识为true,是不是线程就立刻停止?

答案是不立刻停止,具体来说,当对一个线程,调用interrupt时:

  • 如果线程处于正常活动状态,那么会将该线程的中断标志设置为true,仅此而已,被设置中断标志的线程将继续正常运行,不受影响,所以interrupt()并不能真正的中断线程,需要被调用的线程自己进行配合才行,对于不活动的线程没有任何影响。

  • 如果线程处于阻塞状态(例如sleep,wait,join状态等),在别的线程中调用当前线程对象的interrupt方法,那么线程将立即退出被阻塞状态(interrupt状态也将被清除),并抛出一个InterruptedException异常。

第一种情况正常活动状态演示 

package com.nanjing.gulimall.zhouyimo.test;

import java.util.concurrent.TimeUnit;

/**
 * @author zhou
 * @version 1.0
 * @date 2023/10/15 5:43 下午
 * 执行interrupt方法将t1标志位设置为true后,t1没有中断,仍然完成了任务后再结束
 * 在2000毫秒后,t1已经结束称为不活动线程,设置状态为没有任何影响
 */
public class InterruptDemo4 {
    public static void main(String[] args) {
        //实例方法interrupt()仅仅是设置线程的中断状态位为true,不会停止线程
        Thread t1 = new Thread(() -> {
            for (int i = 1; i <= 300; i++) {
                System.out.println("------: " + i);
            }
            /**
             * ------: 298
             * ------: 299
             * ------: 300
             * t1线程调用interrupt()后的中断标志位02:true
             */
            System.out.println("t1线程调用interrupt()后的中断标志位02:" + Thread.currentThread().isInterrupted());
        }, "t1");
        t1.start();

        System.out.println("t1线程默认的中断标志位:" + t1.isInterrupted());//false

        try {
            TimeUnit.MILLISECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        t1.interrupt();//true
        /**
         * ------: 251
         * ------: 252
         * ------: 253
         * t1线程调用interrupt()后的中断标志位01:true
         */
        System.out.println("t1线程调用interrupt()后的中断标志位01:" + t1.isInterrupted());//true

        try {
            TimeUnit.MILLISECONDS.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //2000毫秒后,t1线程已经不活动了,不会产生任何影响
        System.out.println("t1线程调用interrupt()后的中断标志位03:" + t1.isInterrupted());//false
    }
}
t1线程默认的中断标志位:false
------: 1
------: 2
------: 3
------: 4
------: 5
------: 6
------: 7
------: 8
------: 9
------: 10
------: 11
------: 12
------: 13
------: 14
------: 15
------: 16
------: 17
------: 18
------: 19
------: 20
------: 21
------: 22
------: 23
------: 24
------: 25
------: 26
------: 27
------: 28
------: 29
------: 30
------: 31
------: 32
------: 33
------: 34
------: 35
------: 36
------: 37
------: 38
------: 39
------: 40
------: 41
------: 42
------: 43
------: 44
------: 45
------: 46
------: 47
------: 48
------: 49
------: 50
------: 51
------: 52
------: 53
------: 54
------: 55
------: 56
------: 57
------: 58
------: 59
------: 60
------: 61
------: 62
------: 63
------: 64
------: 65
------: 66
------: 67
------: 68
------: 69
------: 70
------: 71
------: 72
------: 73
------: 74
------: 75
------: 76
------: 77
------: 78
------: 79
------: 80
------: 81
------: 82
------: 83
------: 84
------: 85
------: 86
------: 87
------: 88
------: 89
------: 90
------: 91
------: 92
------: 93
------: 94
------: 95
------: 96
------: 97
------: 98
------: 99
------: 100
------: 101
------: 102
------: 103
------: 104
------: 105
------: 106
------: 107
------: 108
------: 109
------: 110
------: 111
------: 112
------: 113
------: 114
------: 115
------: 116
------: 117
------: 118
------: 119
------: 120
------: 121
------: 122
------: 123
------: 124
------: 125
------: 126
------: 127
------: 128
------: 129
------: 130
------: 131
------: 132
------: 133
------: 134
------: 135
------: 136
------: 137
------: 138
------: 139
------: 140
------: 141
------: 142
------: 143
------: 144
------: 145
------: 146
------: 147
------: 148
------: 149
------: 150
------: 151
------: 152
------: 153
------: 154
------: 155
------: 156
------: 157
------: 158
------: 159
------: 160
------: 161
------: 162
------: 163
------: 164
------: 165
------: 166
------: 167
------: 168
------: 169
------: 170
------: 171
------: 172
------: 173
------: 174
------: 175
------: 176
------: 177
------: 178
------: 179
------: 180
------: 181
------: 182
------: 183
------: 184
------: 185
------: 186
------: 187
------: 188
------: 189
------: 190
------: 191
------: 192
------: 193
------: 194
------: 195
------: 196
------: 197
------: 198
------: 199
------: 200
------: 201
------: 202
------: 203
------: 204
------: 205
------: 206
------: 207
------: 208
------: 209
------: 210
------: 211
------: 212
------: 213
------: 214
------: 215
------: 216
------: 217
------: 218
------: 219
------: 220
------: 221
------: 222
------: 223
------: 224
------: 225
------: 226
------: 227
------: 228
------: 229
------: 230
------: 231
------: 232
t1线程调用interrupt()后的中断标志位01:true
------: 233
------: 234
------: 235
------: 236
------: 237
------: 238
------: 239
------: 240
------: 241
------: 242
------: 243
------: 244
------: 245
------: 246
------: 247
------: 248
------: 249
------: 250
------: 251
------: 252
------: 253
------: 254
------: 255
------: 256
------: 257
------: 258
------: 259
------: 260
------: 261
------: 262
------: 263
------: 264
------: 265
------: 266
------: 267
------: 268
------: 269
------: 270
------: 271
------: 272
------: 273
------: 274
------: 275
------: 276
------: 277
------: 278
------: 279
------: 280
------: 281
------: 282
------: 283
------: 284
------: 285
------: 286
------: 287
------: 288
------: 289
------: 290
------: 291
------: 292
------: 293
------: 294
------: 295
------: 296
------: 297
------: 298
------: 299
------: 300
t1线程调用interrupt()后的中断标志位02:true
t1线程调用interrupt()后的中断标志位03:false

Process finished with exit code 0

第二种情况线程处于阻塞状态演示

package com.nanjing.gulimall.zhouyimo.test;

import java.util.concurrent.TimeUnit;

/**
 * @author zhou
 * @version 1.0
 * @date 2023/10/15 9:40 下午
 */

//1.中断标志位默认为false
//2.t2对t1发出中断协商  t1.interrupt();
//3.中断标志位为true: 正常情况 程序停止
  //中断标志位为true  异常情况,.InterruptedException ,将会把中断状态清除,中断标志位为false
//4.需要在catch块中,再次调用interrupt()方法将中断标志位设置为false;
public class InterruptDemo5 {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println(Thread.currentThread().getName() + " 中断标志位为:" + Thread.currentThread().isInterrupted() + " 程序停止");
                    break;
                }
                //sleep方法抛出InterruptedException后,中断标识也被清空置为false,如果没有在
                //catch方法中调用interrupt方法再次将中断标识置为true,这将导致无限循环了
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
                System.out.println("-------------hello InterruptDemo5");

            }
        }, "t1");
        t1.start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            t1.interrupt();
        }, "t2").start();
    }
}
-------------hello InterruptDemo5
-------------hello InterruptDemo5
-------------hello InterruptDemo5
-------------hello InterruptDemo5
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.nanjing.gulimall.zhouyimo.test.InterruptDemo5.lambda$main$0(InterruptDemo5.java:27)
	at java.lang.Thread.run(Thread.java:750)
-------------hello InterruptDemo5
t1 中断标志位为:true 程序停止

详细解释:


静态方法Thread.interrupted(),谈谈你的理解?

package com.nanjing.gulimall.zhouyimo.test;

/**
 * @author zhou
 * @version 1.0
 * @date 2023/10/15 10:17 下午
 */
public class InterruptDemo6 {
    public static void main(String[] args) {
        /**
         * main	false
         * main	false
         * -----------1
         * -----------2
         * main	true
         * main	false
         */
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());//false
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());//false
        System.out.println("-----------1");
        Thread.currentThread().interrupt();
        System.out.println("-----------2");
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());//true
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());//false

    }
}


main	false
main	false
-----------1
-----------2
main	true
main	false

如果调用interrupt方法再次将中断标识置为true:

package com.nanjing.gulimall.zhouyimo.test;

/**
 * @author zhou
 * @version 1.0
 * @date 2023/10/15 10:17 下午
 */
public class InterruptDemo6 {
    public static void main(String[] args) {
        /**
         * main	false
         * main	false
         * -----------1
         * -----------2
         * main	true
         * main	false
         */
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());//false
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());//false
        System.out.println("-----------1");
        Thread.currentThread().interrupt();
        System.out.println("-----------2");
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());//true
        //如果调用interrupt方法再次将中断标识置为true
        Thread.currentThread().interrupt();
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());//false

    }
}


main	false
main	false
-----------1
-----------2
main	true
main	true

对于静态方法Thread.interrupted()和实例方法isInterrupted()区别在于:

静态方法interrupted将会清除中断状态(传入的参数ClearInterrupted为true)

实例方法isInterrupted则不会(传入的参数ClearInterrupted为false) 

总结 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZHOU_VIP

您的鼓励将是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值