中断与中断检测
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()恢复