> 文章列表 > JUC编程之——线程中断机制及源码分析

JUC编程之——线程中断机制及源码分析

JUC编程之——线程中断机制及源码分析

1 什么是中断机制

  • 一个线程不应该由其他线程中断或停止,而应该由线程自行停止——命运掌握在自己手里;
  • 所以Thread.stop、Thread.suspend、Thread.resume方法都已过时;
  • Java中无法立即停止一个线程;
  • Java提供了一种用于停止线程的协商机制——中断,也即中断标识协商机制;
  • 中断过程需要程序员自己实现——用线程的interrupt方法将对象的中断标识设置为true——只是温馨提示,不是强制终止;

2 中断的相关API方法之三大方法说明

  • void interrupt():
    • 中断此线程;
    • 只是设置中断标志位,发起一个协商;
  • static boolean interrupted():
    • 测试当前线程是否已被中断;
    • 静态方法;
    • 方法做了两件事:
      • 返回当前线程的中断状态,测试当前的线程是否已被中断;
      • 将当前线程的中断状态清零并重新设为true,清除线程的中断状态;
  • boolean isInterrupted():
    • 判断当前线程是否被中断(通过检查中断标志位);
    • 和第一个方法配合使用;

3 如何停止中断运行中的线程——代码示例

3.1 通过关键字volatile变量实现

import java.util.concurrent.TimeUnit;public class InterruptDemo
{
private static volatile boolean isStop = false;public static void main(String[] args)
{new Thread(() -> {while(true){// 需要退出了 or 需要中断了if(isStop){System.out.println(Thread.currentThread().getName()+"线程------isStop = true,自己退出了");break;}System.out.println("-------hello interrupt");}},"t1").start();//暂停几秒钟线程try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }isStop = true;
}

3.2 通过AtomicBoolean类实现

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;public class StopThreadDemo
{private final static AtomicBoolean atomicBoolean = new AtomicBoolean(true);public static void main(String[] args){new Thread(() -> {while(true)){if(atomicBoolean.get()){System.out.println(Thread.currentThread().getName() + "\\t atomicBoolean 被修改为true 线程停止");break;}System.out.println("t1-----hello");}}, "t1").start();// 小睡一会try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }// 另一个线程new Thread(() -> {atomicBoolean.set(true);},"t2").start();}
}}

3.3 通过Thread类自带的中断API方法实现

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;public class InterruptTest {public static void main(String[] args) {Thread t1 = new Thread(() -> {while(true) {// 中断if(Thread.currentThread().isInterrupted()) {System.out.println(Thread.currentThread().getName() + "\\t 中断");break;}System.out.println("----t1 interrupt");}},"t1");t1.start();try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {throw new RuntimeException(e);}new Thread(() -> {t1.interrupt();},"t2").start();}
}

4 中断方法底层源码分析

4.1 interrupt()方法——无返回值

  • interrupt方法作用:中断此线程;
  • 仅仅是将中断标识位从false设置为true
  • 并不是立刻停止线程
  • 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),在别的线程中调用当前线程对象的interrupt方法,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。;
  • 中断不活动的线程不会产生任何影响;
    public void interrupt() {if (this != Thread.currentThread())checkAccess();synchronized (blockerLock) {Interruptible b = blocker;if (b != null) {// 实际调用interrupt0()interrupt0();           // Just to set the interrupt flagb.interrupt(this);return;}}interrupt0();}

调用底层native方法:

    private native void interrupt0();

4.2 isInterrupted()方法

public boolean isInterrupted() {return isInterrupted(false);}

底层还是调用native方法:

// Tests if some Thread has been interrupted. 
// The interrupted state is reset or not based on the value of ClearInterrupted that is passed.private native boolean isInterrupted(boolean ClearInterrupted);