java中线程中断的实现示例
作者:Michael_lcf
1、线程中断 即 线程的取消/关闭的机制
Java中停止一个线程的主要机制是中断,中断并不是强迫终止一个线程,它是一种 协作机制
,是给线程传递一个取消/关闭信号,由线程自身来决定如何以及何时退出。
停止线程,但这个方法被标记为了过时。 @Deprecated public final void stop() ========================= 返回对应线程的中断标志位是否为true。 public boolean isInterrupted() 返回当前线程的中断标志位是否为true,并清空中断标志位。 public static boolean interrupted() 表示中断对应的线程。 public void interrupt()
2、线程对中断interrupt()的反应
2.1、RUNNABLE:线程在运行或具备运行条件只是在等待操作系统调度
举个栗子:
public static void main(String[] args) throws InterruptedException { Thread t = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { System.out.println("线程t 执行中..."); } }); t.start(); Thread.sleep(1); t.interrupt(); System.out.println("main exit"); }
RUNNABLE状态的线程t
被interrupt()
后,是否终止中断线程由线程t
自身代码逻辑决定。
2.2、WAITING/TIMED_WAITING:线程在等待某个条件或超时
线程执行如下方法会进入WAITING状态: public final void join() throws InterruptedException public final void wait() throws InterruptedException 线程执行如下方法会进入TIMED_WAITING状态: public final native void wait(long timeout) throws InterruptedException public static native void sleep(long millis) throws InterruptedException public final synchronized void join(long millis) throws InterruptedException
举个栗子:
public class ThreadInterrupt { public static void main(String[] args) { Thread t = new Thread(() -> { try { Thread.sleep(10000); } catch (InterruptedException e) { System.out.println("Thread.interrupted() = " + Thread.interrupted()); //Thread.interrupted() = false System.out.println("Thread.interrupted() = " + Thread.interrupted()); //Thread.interrupted() = false } }); t.start(); t.interrupt(); } }
捕获到InterruptedException,通常表示希望结束该线程,线程大概有两种处理方式:
向上传递该异常,这使得该方法也变成了一个可中断的方法,需要调用者进行处理。
有些情况,不能向上传递异常,比如Thread的run方法,它的声明是固定的,不能抛出任何受检异常,这时,应该捕获异常,进行合适的清理操作,清理后,一般应该调用Thread的interrupt方法设置中断标志位,使得其他代码有办法知道它发生了中断。
2.3、BLOCKED:线程在等待锁,试图进入同步块
举个栗子:
public class ThreadInterrupt { private final static Object lockObj = new Object(); private static class MyBlockedThread extends Thread { @Override public void run() { System.out.println("MyBlockedThread.run = " + Thread.currentThread().isInterrupted()); synchronized (lockObj) { while (!Thread.currentThread().isInterrupted()) { System.out.println(Thread.currentThread().isInterrupted()); } } System.out.println("exit"); } } public static void main(String[] args) throws InterruptedException { synchronized (lockObj) { MyBlockedThread myBlockedThread = new MyBlockedThread(); myBlockedThread.start(); Thread.sleep(3000); myBlockedThread.interrupt(); myBlockedThread.join(); // join方法会等待线程执行完后返回 } } }
myBlockedThread.join();
该行代码放开注释掉情况下:线程一直等待锁 BLOCKED。
com.michael.ThreadInterrupt.MyBlockedThread.run = false
myBlockedThread.join();
该行代码注释掉情况下:因为主线程不再等待线程myBlockedThread结束,释放锁lock后,线程myBlockedThread会获得锁,然后检测到发生了中断,然后程序退出。
com.michael.ThreadInterrupt.MyBlockedThread.run = false exit
2.4、NEW/TERMINATED:线程还未启动或已结束
举个栗子:
public static void main(String[] args) throws InterruptedException { Thread t = new Thread(() -> { System.out.println("线程t 执行..."); }); t.interrupt(); System.out.println("NEW = " + t.isInterrupted()); t.start(); Thread.sleep(100); t.interrupt(); System.out.println("TERMINATE = " + t.isInterrupted()); } ============ 执行结果 ============ NEW = false 线程t 执行... TERMINATE = false
2.5、IO操作
如果线程在等待IO操作,尤其是网络IO,则会有一些特殊的处理。
- 如果IO通道是可中断的,即实现了
InterruptibleChannel
接口,则线程的中断标志位会被设置,同时线程会收到异常ClosedByInterruptException
。 - 如果线程阻塞于
Selector
调用,则线程的中断标志位会被设置,同时阻塞的调用会立即返回。 InputStream的read
调用,该操作是不可中断的,如果流中没有数据,read
会阻塞 (但线程状态依然是RUNNABLE
),且不响应interrupt()
,与synchronized
类似,调用interrupt()
只会设置线程的中断标志,而不会真正"中断"。
3、关于中断的经验
Java中取消/关闭线程技术是中断,但它是一种协作机制,不会强制终止线程。线程在不同状态和IO操作时对中断的反应有所不同。
作为线程的实现者:应该提供明确的取消/关闭方法,并用文档描述清楚其行为。
作为线程的调用者:应该使用其取消/关闭方法,而不是贸然调用interrupt()方法。
到此这篇关于java中线程中断的实现示例的文章就介绍到这了,更多相关java 线程中断内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!