java中断机制

java中断机制

java 提供一个非抢占式的中断机制.它是java语言级提供的一种线程间协作机制.

抢占式与非抢占式
抢占式(Preemptive) 指任务之间可以不管互相是否在运行中状态,都可以将抢占对方的CPU计算时间.这种策略可以防止单一任务长时间占用CPU.
非抢占式(Nonpreemptive) 指任务之间不可互相打断运行中状态.Java采用这种策略,使得中断更灵活.(也更麻烦)

中断有什么用?

中断在取消与关闭线程的场景里用的最多.
想想不用中断我们是怎样关闭其余线程的.

public class Main {

    private static volatile boolean cancelled = false;

    public static void main(String [] args) throws InterruptedException {
        MyRunnable myRunnable = new MyRunnable();
        new Thread(myRunnable).start();
        Thread.sleep(3000);
        System.out.println("Change cancelled to true!");
        cancelled = true;
    }

    static class MyRunnable implements Runnable{
        public void run() {
            while (!cancelled){
                try {
                    doSomething();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("Thread exit!");
        }
    }
}

通过一个全局变量作为线程开关标志,子线程定时检查该标志是否关闭来决定子线程的关闭与否.

但是这样的代码会有一个潜在的隐患—-doSomething()方法有可能是阻塞方法(比如BlockingQueue.put()sleep()),那子线程就有可能永远不会停止.这当然不是我们想要的.怎么办?
中断在这个时候就非常好用!有点类似于这里的cancelled标志,中断状态通过以下方法来读取和控制:

public class Thread{
    //中断线程
    public void interrupt() {...}
    //返回线程的中断状态
    public boolean isInterrupted() {...}
    //清除中断状态,并返回之前的值
    public static boolean interrupted() {...}
}

而与我们自定义的全局变量标志不同的是,java阻塞库方法(比如方法BlockingQueue.put()sleep())在运行的过程中会检查中断状态(不同与我们在代码中的做法,检查中断是java语言级支持的功能,所以效率和稳定性都很高),万一发现线程被中断,就会结束进程运行并抛出InterruptedException.
具体说久是如果上面的doSomething()方法是Thread.sleep().当我们中断子线程的时候,sleep()会(几乎)立即停止运行并抛出异常!

但如果是非阻塞的方法,如果不显式地处理中断,线程的运行状态并不会发生改变!这个要千万注意! 比如
以下代码

public class Main {

    private static volatile boolean cancelled = false;

    public static void main(String [] args) throws InterruptedException {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
        Thread.sleep(1000);
        System.out.println("Change cancelled to true!");
        thread.interrupt();
    }

    static class MyRunnable implements Runnable{
        public void run() {
            while (true){
                    doSomething();
            }
        }

        private void doSomething(){
            waiting();
            System.out.println("I am running!");
        }

        private void waiting(){
            Long count = 1000000000l;
            while (count-- > 0);
        }
    }
}

输出:
这里写图片描述
子线程并不会对中断做出相应,继续执行.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值