Java多线程之interrupt()的深度研究
2014-01-12 18:04
316 查看
近期学习Java多线程的中断机制,网上的帖子说得很浅,并没深究其原理。看了Java源码,对Java的中断机制有了略深入的理解,在这篇文章中向感兴趣的网友分享下。这篇文章主要通过一个典型例子对中断机制进行剖析。
一:一些概念和重要方法
interrupt status(中断状态):请记住这个术语,中断机制就是围绕着这个字段来工作的。在Java源码中代表中断状态的字段是:private volatile Interruptible blocker;对“Interruptible”这个类不需要深入分析,对于“blocker”变量有以下几个操作。
1.默认blocker=null; ®1
2.调用方法“interrupt0();”将会导致“该线程的中断状态将被设置(JDK文档中术语)”。®2
3.再次调用“interrupt0();”将会导致“其中断状态将被清除(同JDK文档中术语)”®3
注:这三点很重要,接下来文章中会用来[b]®1[b]®2[b]®3[/b][/b]代替。[/b]
明白了第一点来看下文档中对于中断线程相关方法的描述。
1.public void interrupt();
中断线程。如果线程在调用
过程中受阻,则其中断状态将被清除,它还将收到一个
2.public static boolean interrupted();
测试当前线程是否已经中断。线程的中断状态 由该方法清除。线程中断被忽略,因为在中断时不处于活动状态的线程将由此返回 false 的方法反映出来。
返回: 如果当前线程已经中断,则返回
3.public boolean isInterrupted();
测试线程是否已经中断。线程的中断状态 不受该方法的影响。线程中断被忽略,因为在中断时不处于活动状态的线程将由此返回 false 的方法反映出来。
返回:如果该线程已经中断,则返回
另请参见:
<!--来自JDK API文档-->
以上三段中关于线程的中断状态 由该方法清除的描述,在源码层面就是®3调用。
接下来说一下"interrupted()"和"isInterrupted()"两个方法的相同点和不同点。在这之前看一下源码中两个方法的代码,如下:
相同点都是判断线程的interrupt status是否被设置,若被设置返回true,否则返回false.区别有两点:一:前者是static方法,调用者是current thread,而后者是普通方法,调用者是this current.二:它们其实都调用了Java中的一个native方法isInterrupted(boolean ClearInterrupted); 不同的是前者传入了参数true,后者传入了false.意义就是:前者将清除线程的interrupt state(®3),调用后者线程的interrupt state不受影响。
二:例子。
接下来看一个例子,这个例子说明了两个问题。1.调用interrupt()方法并不会中断一个正在运行的线程.2.若调用sleep()而使线程处于阻塞状态,这时调用interrupt()方法,会抛出InterruptedException,从而使线程提前结束阻塞状态,退出阻塞代码。如下:
运行结果:
三:分析下例子中的中断机制
1.为什么调用interrupt()并不能中断线程?
如上是Java源码中的代码,由此我们看出问题的答案。线程的blocker字段(也就是interrupt status)默认是null(®1)。调用interrupt()方法时,只是运行了®2,并没有进入if语句,所以没调用真正执行中断的代码b.interrupt().
2.若调用sleep()而使线程处于阻塞状态,这时调用interrupt()方法,会抛出InterruptedException,从而使线程提前结束阻塞状态,退出阻塞代码。为什么?
由上图可看出例子中30行代码铺好的异常其实是interrupt()抛出的,而不是sleep()抛出的。
欢迎交流!
Author:Andy Zhai
2014-01-12 17:54:39
一:一些概念和重要方法
interrupt status(中断状态):请记住这个术语,中断机制就是围绕着这个字段来工作的。在Java源码中代表中断状态的字段是:private volatile Interruptible blocker;对“Interruptible”这个类不需要深入分析,对于“blocker”变量有以下几个操作。
1.默认blocker=null; ®1
2.调用方法“interrupt0();”将会导致“该线程的中断状态将被设置(JDK文档中术语)”。®2
3.再次调用“interrupt0();”将会导致“其中断状态将被清除(同JDK文档中术语)”®3
注:这三点很重要,接下来文章中会用来[b]®1[b]®2[b]®3[/b][/b]代替。[/b]
明白了第一点来看下文档中对于中断线程相关方法的描述。
1.public void interrupt();
中断线程。如果线程在调用
Object类的
wait()、
wait(long)或
wait(long, int)方法,或者该类的
join()、
join(long)、
join(long, int)、
sleep(long)或
sleep(long, int)方法
过程中受阻,则其中断状态将被清除,它还将收到一个
InterruptedException。
2.public static boolean interrupted();
测试当前线程是否已经中断。线程的中断状态 由该方法清除。线程中断被忽略,因为在中断时不处于活动状态的线程将由此返回 false 的方法反映出来。
返回: 如果当前线程已经中断,则返回
true;否则返回
false。 另请参见:
isInterrupted()
3.public boolean isInterrupted();
测试线程是否已经中断。线程的中断状态 不受该方法的影响。线程中断被忽略,因为在中断时不处于活动状态的线程将由此返回 false 的方法反映出来。
返回:如果该线程已经中断,则返回
true;否则返回
false。
另请参见:
interrupted()
<!--来自JDK API文档-->
以上三段中关于线程的中断状态 由该方法清除的描述,在源码层面就是®3调用。
接下来说一下"interrupted()"和"isInterrupted()"两个方法的相同点和不同点。在这之前看一下源码中两个方法的代码,如下:
public static boolean interrupted() { return currentThread().isInterrupted(true); } public boolean isInterrupted() { return isInterrupted(false); } /** * Tests if some Thread has been interrupted. The interrupted state * is reset or not based on the value of ClearInterrupted that is * passed. */ private native boolean isInterrupted(boolean ClearInterrupted);
相同点都是判断线程的interrupt status是否被设置,若被设置返回true,否则返回false.区别有两点:一:前者是static方法,调用者是current thread,而后者是普通方法,调用者是this current.二:它们其实都调用了Java中的一个native方法isInterrupted(boolean ClearInterrupted); 不同的是前者传入了参数true,后者传入了false.意义就是:前者将清除线程的interrupt state(®3),调用后者线程的interrupt state不受影响。
二:例子。
接下来看一个例子,这个例子说明了两个问题。1.调用interrupt()方法并不会中断一个正在运行的线程.2.若调用sleep()而使线程处于阻塞状态,这时调用interrupt()方法,会抛出InterruptedException,从而使线程提前结束阻塞状态,退出阻塞代码。如下:
package interrupt; public class Main { /** * @param args */ public static void main(String[] args) { Main main = new Main(); Thread t = new Thread(main.runnable); System.out.println("mainmainmain"); t.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t.interrupt(); } Runnable runnable = new Runnable() { @Override public void run() { int i = 0; try { while (i < 1000) { Thread.sleep(500); System.out.println(i++); } } catch (InterruptedException e) { e.printStackTrace(); } } }; }
运行结果:
mainmainmain 0 1 2 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at interrupt.Main$1.run(Main.java:27) at java.lang.Thread.run(Thread.java:619)
三:分析下例子中的中断机制
1.为什么调用interrupt()并不能中断线程?
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(); return; } } interrupt0(); }
如上是Java源码中的代码,由此我们看出问题的答案。线程的blocker字段(也就是interrupt status)默认是null(®1)。调用interrupt()方法时,只是运行了®2,并没有进入if语句,所以没调用真正执行中断的代码b.interrupt().
2.若调用sleep()而使线程处于阻塞状态,这时调用interrupt()方法,会抛出InterruptedException,从而使线程提前结束阻塞状态,退出阻塞代码。为什么?
由上图可看出例子中30行代码铺好的异常其实是interrupt()抛出的,而不是sleep()抛出的。
欢迎交流!
Author:Andy Zhai
2014-01-12 17:54:39
相关文章推荐
- Java多线程之interrupt()的深度研究
- Java多线程之interrupt()的深度研究
- Java多线程研究03-线程的基本操作(notify,notifyAll,interrupt,join,sleep)
- java 多线程 中断线程interrupt 研究
- Java多线程系列--【基础篇09】- interrupt()和线程终止方式
- Java 线程与并发研究系列四(多线程)
- java多线程(二) sleep(),yield(),wait(), interrupt()方法
- Java多线程-Thread.interrupt()到底意味着什么
- java基础---->多线程之interrupt(九)
- Java多线程技术研究(一)-多线程的创建及常见名词
- Java 多线程 join和interrupt 方法
- Java的多线程研究(四)
- java多线程总结三:sleep()、join()、interrupt()示例
- Java多线程研究(八)使用Exchange在多个线程间交换数据
- java多线程总结三:sleep()、join()、interrupt()示例
- Android多线程研究(8)——Java中的原子性理解
- Java多线程深度探索
- Java多线程(5) interrupt
- Java多线程研究04-线程池的使用(ThreadPoolExecutor详解)
- Java多线程(二)——线程中断interrupt