4.线程中断

本文详细解析了Java中线程中断的实现机制,包括interrupt方法的作用、isInterrupted与interrupted方法的区别及应用场景,并提供了具体的代码示例。

总结

  • 通过interrupt设置线程的中断标志位,并不能直接终止该线程,而是被中断的线程根据中断状态自行处理。
  • isInterrupted和interrupted都是检测线程是否被中断,区别在于isInterrupted可判断线程的中断情况,interrupted只能判断执行当前代码的线程的中断情况,后者会重置线程标志位为false。

1.线程中断三个关键方法

1.1 void interrupt()

中断线程。线程B调用线程A的interrupt方法,设置中断标志位为true后,立即返回。至于线程A什么时候被中断,需要线程A自行决定。例如,线程A因为调用了wait,sleep,join方法被阻塞挂起后,线程B调用了A的interrupt方法,线程A会在会在上述阻塞方法处抛出InterruptedException异常。

1.2 boolean isInterrupted()

检测线程是否被中断,返回true/false。

1.3 boolean interrupted()静态方法

检测当前线程是否被中断,返回true/false。若发现当前线程被中断,则会清除中断标志

内部实现:

return currentThread().isInterrupted(true);

2. 线程中断代码示例

2.1 使用isInterrupted优雅退出经典模式:

 public  void run(){
        try{
            while (!Thread.currentThread().isInterrupted() && ***){
                //do work
            }
        }catch (InterruptedException e){
            //thread was interrupted during sleep or wail or join
            e.printStackTrace();
        }finally {
            //clean resources
        }
    }

2.2 使用interrupt中断线程代码实例:

public  static void  main(String[] args) throws  InterruptedException{
        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    System.out.println("Thread one start sleep 20 s");
                    Thread.sleep(20000);
                    System.out.println("Thread one sleep over");
                }catch (InterruptedException e){
                    System.out.println("Thread one is interrupted while sleeping");
                    e.printStackTrace();
                    return;
                }
                System.out.println("Thread one leaving normaly");
            }
        });

        threadOne.start();
        Thread.sleep(1000);//主线程睡1秒

        threadOne.interrupt();//设置标志位中断线程

        threadOne.join();//让子线程运行结束
        System.out.println("main thread run over ...");

    }

输出:

Thread one start sleep 20 s
Thread one is interrupted while sleeping
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.evan.wj.ThreadTest$1.run(ThreadTest.java:10)
	at java.lang.Thread.run(Thread.java:748)
main thread run over ...

2.3 对比Interrupted和isInterrupted区别

代码实例1:

public  static void  main(String[] args) throws  InterruptedException{
        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true);
            }
        });

        threadOne.start();
        threadOne.interrupt();//设置中断标志

        System.out.println("第一次isInterrupted:"+threadOne.isInterrupted());//true
        System.out.println("第一次interrupted:"+threadOne.interrupted());//false
        System.out.println("第二次interrupted:"+threadOne.interrupted());//false
        System.out.println("第二次isInterrupted:"+threadOne.isInterrupted());//true

        System.out.println("main thread run over ...");

    }

输出:

第一次isInterrupted:true
第一次interrupted:false
第二次interrupted:false
第二次isInterrupted:true
main thread run over ...

解释:

第一个true,很简单,因为先设置了线程中断标志位,后判断是否被中断,返回true。

第二个false,interrupted调用的是currentThread.isInterrupted(true),因此表示主线程的线程中断标志位,当然为false。

第三个false,同第二次一样。

第四个true,由于isInterrupted并不会清除线程中断标志位,因此返回的依旧是true。

代码示例2:实践表明interrupted会清除中断标志位

 public  static void  main(String[] args) throws  InterruptedException{
        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().interrupted()){//清除了中断标志位
                }
                System.out.println("线程内isInterrupted:"+Thread.currentThread().isInterrupted());
            }
        });
        threadOne.start();

        threadOne.interrupt();//设置中断标志
        threadOne.join();
        System.out.println("main thread run over ...");
    }

输出:

线程内isInterrupted:false
main thread run over ...

解释:线程内部的interrupted重置了线程标志位,因此后面线程内的isInterrupted输出为false。
 

### 解决 `CountDownLatch.await` 方法在线程中断时的问题 当调用 `countDownLatch.await()` 时,如果当前线程中断,则会抛出 `InterruptedException` 异常[^1]。为了妥善处理这种情况,可以在捕获到异常后执行相应的逻辑来响应中断。 下面是一个完整的解决方案示例: ```java import java.util.concurrent.CountDownLatch; public class InterruptibleLatchExample { public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(1); Thread workerThread = new Thread(() -> { try { // Simulate some work being done. System.out.println("Worker thread is working..."); Thread.sleep(2000); // Signal that the task has been completed. System.out.println("Worker thread finished its job."); latch.countDown(); } catch (InterruptedException e) { System.err.println("Worker thread was interrupted!"); } }); workerThread.start(); try { // Wait until the latch reaches zero or an interruption occurs. latch.await(); System.out.println("Main thread continues after all tasks are complete."); } catch (InterruptedException ie) { // Handle the case where this thread gets interrupted while waiting on the latch. System.err.println("The main thread was interrupted before completion of other threads' jobs."); // Restore the interrupt status since it's good practice when catching and handling interrupts. Thread.currentThread().interrupt(); } // Optionally check whether any remaining operations need to be handled due to early termination. if (latch.getCount() > 0L) { System.out.println("Some workers did not finish their jobs properly."); } } } ``` 在这个例子中,程序创建了一个新的工作线程并启动它去模拟一些耗时的任务。与此同时,在主线程里调用了 `await()` 来等待这个任务结束。一旦发生中断事件,无论是发生在工作者线程还是主线程上,都会被捕获,并且可以采取适当措施恢复或记录错误信息。此外,还展示了如何重新设置线程中断标志位以便后续代码能够继续识别中断状态[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值