中断

中断与中断检测

Thread类中相关方法

//设置中断标志,而不是真的中断
public void interrupt() {
    if (this != Thread.currentThread())
        checkAccess();

    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            interrupt0();           // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
    interrupt0();
}

//静态方法,会清除中断标志,连续两次调用该方法,第二次会返回false
public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}

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

private native boolean isInterrupted(boolean ClearInterrupted);

private native void interrupt0();

isInterrupted()检测中断例子

public static void f(){
    try{
        TimeUnit.SECONDS.sleep(1);
    } catch(InterruptedException e) {

    }
}

public static void main(String[] args) {
    Thread thread = new Thread(Solution::f);
    thread.start();
    thread.interrupt();
    System.out.println(thread.isInterrupted());//true
}

interrupted()检测中断例子

public static void main(String[] args) {
    Thread.currentThread().interrupt();
    System.out.println(Thread.interrupted());//true
    System.out.println(Thread.interrupted());//false,证明会清除中断标志
}

关于isInterrupted返回值的疑惑

public static void f(){
    try{
        TimeUnit.SECONDS.sleep(1);
    } catch(InterruptedException e) {

    }
}

public static void main(String[] args) {
    Thread thread = new Thread(Solution::f);
    thread.start();
    thread.interrupt();
    try{
        TimeUnit.SECONDS.sleep(1);//sleep一会,thread应该已经停止了
    } catch(InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(thread.isInterrupted());//false
}

猜测:isInterrupted对于正在运行的线程才有效

public static void f() {
    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        System.out.println(Thread.interrupted());
        //耗费时间,为了让main先执行
        try{
            TimeUnit.SECONDS.sleep(2);
        } catch(InterruptedException e2) {
            e.printStackTrace();
        }
        System.out.println(Thread.interrupted());
    }
}

public static void main(String[] args) {
    Thread thread = new Thread(Solution::f);
    thread.start();
    thread.interrupt();
    try{
        TimeUnit.SECONDS.sleep(1);
    } catch(InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("isInterrupted:"+thread.isInterrupted());

}

输出的结果是:

false
isInterrupted:false
false

说明之前猜测错误

如果一个线程处于了阻塞状态(如线程调用了thread.sleep、thread.join、thread.wait、condition.await、以及可中断的通道上的 I/O 操作方法后可进入阻塞状态),则在线程在检查中断标示时如果发现中断标示为true,则会在这些阻塞方法调用处抛出InterruptedException异常,并且在抛出异常后立即将线程的中断标示位清除,即重新设置为false。抛出异常是为了线程从阻塞状态醒过来,并在结束线程前让程序员有足够的时间来处理中断请求。

在线程中断标记清除之前对中断检测才会返回true

中断处理

方法一:检测到中断手工处理

public static void f() {
    while (true) {
        if(Thread.interrupted()){
            System.out.println("interrupt");
            break;
        }
        doSomething();
    }
}
public static void doSomething(){

}

public static void main(String[] args) {
    Thread thread = new Thread(Solution::f);
    thread.start();
    thread.interrupt();
}

方法二:检测到中断抛异常

public static void f() throws InterruptedException {
    while (true) {
        if(Thread.interrupted()){
            throw new InterruptedException();
        }
        doSomething();

    }
}
public static void doSomething(){

}

public static void main(String[] args)  {
    Thread thread = new Thread(()->{
        try {
            f();
        } catch (InterruptedException e) {
            System.out.println("interrupt");
        }
    });
    thread.start();
    thread.interrupt();
}

方法三:捕获中断异常

public static void f()  {
    while (true) {
        try {
            doSomething();
        } catch (InterruptedException e) {
            System.out.println("interrupt");
            break;
        }

    }
}
public static void doSomething() throws InterruptedException {
    TimeUnit.SECONDS.sleep(1);
}

public static void main(String[] args)  {
    Thread thread = new Thread(Solution::f);
    thread.start();
    thread.interrupt();
}

stop

@Deprecated
public final void stop() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        checkAccess();
        if (this != Thread.currentThread()) {
            security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
        }
    }
 
    if (threadStatus != 0) {
        resume(); // Wake up thread if it was suspended; no-op otherwise
    }

    // The VM can handle all thread states
    stop0(new ThreadDeath());
}

private native void stop0(Object o);

interrupt是设置线程的中断状态,由用户去选择结束线程,stop是会直接抛ThreadDeath extends Error

public static void f() {
    try {
        //做一个耗时的操作
        int[] a = new int[100000000];
        for (int i = 0; i < a.length; i++) {
            Arrays.sort(a);
        }
    } catch (ThreadDeath e) {
        System.out.println("处理异常....");
    }
}

public static void main(String[] args) {
    Thread thread = new Thread(Solution::f);
    thread.start();
    System.out.println("stop");
    thread.stop();
}

对于正持有锁的线程,stop会释放锁,可能造成对象的不一致

suspend():可以中断持有锁的线程,但不会释放锁,可能造成死锁,可以用resume()恢复

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值