Thread中相关中断方法
1.interrupt() 中断线程,本质是将线程的中断标志位设为true,其他线程向需要中断的线程发出中断请求,然后什么时候中断由线程自己决定。
2.isInterrupted() 检查线程中断标志位
3.interrupted() 此方法为静态方法,用于将中断标志位复位为false
java的中断的机制是协作式任务,而非抢占式任务,也就是说线程可以通过中断的方式来通知另一个线程,让其在合适的或者可能的情况下停止当前工作。下面将给大家分享在三种场景下,中断停止线程的运行
非阻塞情况下线程的中断方式
在非阻塞的情况下,只需使用volatile关键字来修饰变量作为开关,因为volatile是可以是变量线程可见
public class SafeInterrupt extends Thread { private volatile boolean cancel = false; private long i =0; @Override public void run() { while(!cancel){ i++; System.out.println(i); } System.out.println("the end :"+i); } public void cancel(){ cancel = true; }}
然而在阻塞的情况下,这种方法就行不通了,接下来我们看一下在阻塞的情况下该如何中断线程
阻塞情况下线程的中断方式
捕获InterruptedException的同时调用interrupt来恢复中断,这样在while条件中使用isInterrupted() 来检查线程中断标志位。
注:程序在抛出InterruptedException后,会清除中断标识为也就是将中断标志位复位为false
public class SafeInterrupt extends Thread { private static Object o =new Object(); private long i =0; @Override public void run() { while (!Thread.currentThread().isInterrupted()) { System.out.println(i++); //抛出中断异常的阻塞方法,抛出异常后,中断标志位改成false try { synchronized (o){ o.wait(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); }finally { //清理工作结束线程 } } } public void cancel() { interrupt(); }}
或者
public class SafeInterrupt extends Thread { private volatile boolean cancel = false; private static Object o =new Object(); private long i =0; @Override public void run() { while (!cancel) { System.out.println(i++); //抛出中断异常的阻塞方法,抛出异常后,中断标志位改成false try { synchronized (o){ o.wait(); } } catch (InterruptedException e) { }finally { //清理工作结束线程 } } } public void cancel() { cancel=true; interrupt(); } }
不可中断的阻塞情况下线程的中断方式
IO通信 inputstream read/write等阻塞方法,不会响应中断,并且关闭底层的套接字socket.close()会抛出socketException
NIO: selector.select()会阻塞,调用selector的wakeup和close方法会抛出ClosedSelectorException死锁状态不响应中断的请求,这个必须重启程序,修改错误。
处理这种中断的方式:覆盖线程的interrupt方法,在处理套接字异常时,再用super.interrupt()自行中断线程
public class SafeInterrupt extends Thread { private final Socket socket; private final InputStream in; public SafeInterrupt(Socket socket, InputStream in) { this.socket = socket; this.in = in; } @Override public void interrupt() { try { //关闭底层的套接字 socket.close(); } catch (IOException e) { e.printStackTrace(); //..... }finally { //同时中断线程 super.interrupt(); } } public void cancel(){ interrupt(); }}