【Java】中断

中断是计算机中一个很大的概念,被广泛用在各种领域中。这里主要介绍下java语言中线程的中断以及InterruptedException异常。

在java语言里,这一逻辑其实很简单。java的线程中断api只是为该线程打上一个中断的标记,并不能真正的中断一个线程。如果想要实现中断操作,需要业务去根据标记做编程。大多数情况下,中断的操作就是抛出一个InterruptedException的异常。当然抛出这个异常,需要由业务来完成。

线程的中断

中断api:

    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();
    }

    private native void interrupt0();

调用thread的interrupt方法,就会为当前线程设置中断标记。其最终实现是native的。

检测中断标记api:

有两个方法:

静态

    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

非静态

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

区别在于:

1)interrupted()是静态方法,当然最终也会调用currentThread拿到当前的线程对象;

2)interrupted()会清除当前线程的中断标记,而isInterrupted则不会。

二者最终都会进入下面的方法:

    /**
     * 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);

也是一个native方法,入参可以指定是否清除标记。

 

InterruptedException异常

public
class InterruptedException extends Exception {
    private static final long serialVersionUID = 6700697376100628473L;

    /**
     * Constructs an <code>InterruptedException</code> with no detail  message.
     */
    public InterruptedException() {
        super();
    }

    /**
     * Constructs an <code>InterruptedException</code> with the
     * specified detail message.
     *
     * @param   s   the detail message.
     */
    public InterruptedException(String s) {
        super(s);
    }
}

该异常是一个Exception的子类,说明这是一个checked异常,需要写入签名,并try-catch。大多数情况下,这个异常就是被中断的实际行为的体现。

一些api,通常是阻塞api会抛出这个异常,表明被中断。比如说sleep函数:

    public static native void sleep(long millis) throws InterruptedException;

当然这也是一个native的方法。

或者说future的get方法:

    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

private int awaitDone(boolean timed, long nanos)
        throws InterruptedException {
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
            if (Thread.interrupted()) {
                removeWaiter(q);
                throw new InterruptedException();
            }

            int s = state;
            if (s > COMPLETING) {
                if (q != null)
                    q.thread = null;
                return s;
            }
            else if (s == COMPLETING) // cannot time out yet
                Thread.yield();
            else if (q == null)
                q = new WaitNode();
            else if (!queued)
                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                     q.next = waiters, q);
            else if (timed) {
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L) {
                    removeWaiter(q);
                    return state;
                }
                LockSupport.parkNanos(this, nanos);
            }
            else
                LockSupport.park(this);
        }
    }

可以看到其内部实现调用了Thread的方法检测是否有中断标记,如果有就抛出InterruptedException异常。

 

自己写一个处理中断的例子:

class Task{

    public void run() throws InterruptedException {
        while(true){
            if (Thread.currentThread().isInterrupted()) {
                throw new InterruptedException();
            }
            Thread.sleep(1000);
            System.out.println("running");
        }
    }
}

public class Main {

    public static void main(String args[]) {
        Thread t1 = new Thread(() -> {
            try {
                new Task().run();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                Thread.sleep(5000);
                t1.interrupt();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t1.start();
        t2.start();
    }
}

 

总结:

java线程中断只是为线程打上标记,其他的不会去做。真正的中断行为需要业务代码去实现。

java中有关线程中断的api有三个。

中断通常与阻塞api有关,中断的过程通常可以是抛出一个InterruptedException。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值