您的位置:首页 > 编程语言 > Java开发

java中断机制

2016-06-08 17:27 337 查看

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


输出:



子线程并不会对中断做出相应,继续执行.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java