- 线程的中断
- 关于interrupt(),java的jdk文档描述如下:API点击
- Interrupts this thread.
Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.
If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.
If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread’s interrupt status will be set, and the thread will receive a ClosedByInterruptException.
If this thread is blocked in a Selector then the thread’s interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector’s wakeup method were invoked.
If none of the previous conditions hold then this thread’s interrupt status will be set.
Interrupting a thread that is not alive need not have any effect. - interrupt()的作用是中断本线程。
本线程中断自己是被允许的;其它线程调用本线程的interrupt()方法时,会通过 checkAccess() 检查权限。这有可能抛出SecurityException异常。
如果本线程是处于阻塞状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也会让它进入阻塞状态。
若线程在阻塞状态时,调用了它的interrupt()方法,那么它的“中断状态”会被清除并且会收到一个InterruptedException异常。
例如,线程通过wait()进入阻塞状态,此时通过interrupt()中断该线程;调用interrupt()会立即将线程的中断标记设为“true”,但是由于线程处于阻塞状态,所以该“中断标记”会立即被清除为“false”,同时,会产生一个InterruptedException的异常。
如果线程被阻塞在一个Selector选择器中,那么通过interrupt()中断它时;线程的中断标记会被设置为true,并且它会立即从选择操作中返回。
如果不属于前面所说的情况,那么通过interrupt()中断线程时,它的中断标记会被设置为“true”。
中断一个“已终止的线程”不会产生任何操作。
- Interrupts this thread.
- 中断就是让目标线程停止执行的意思,但并不是和stop()一样。
- Thread中的stop()和suspend()方法,由于固有的不安全性,已经建议不再使用!
- 严格来讲,线程中断并不会使线程立即退出,而是给线程发出一个通知,告知目标线程,有人希望你退出!目标线程收到通知后如何处理,则完全由目标线程自行决定。
- 常用的线程中断有三个方法 (第一个需要和后面两个的任意一个联用):
-
public static Thread.interrupt() //中断线程
- 一个实例方法、它通知目标线程中断、也就是设置中断标志位(表示当前线程已经被中断了)
- 相应源码:
-
public boolean Thread.isInterrupted() //判断是否被中断
- 一个实例方法,判断当前线程是否被中断(通过检查中断标志位)
- 相应源码:
-
public static boolean Thread.interrupted() //判断是否被中断,并清除当前中断状态,即将中断标记设为false)
- 同上、同时清除当前线程的中断标志位状态
-
interrupt 代码示例:
- 这样做有什么后果呢?
- 答:没有!虽然对t1进行了中断,但是在t1中并没有中断处理的逻辑,因此即使t1线程被设置为中断状态,这个中断也不会发生任何作用 (这时候需要和isInterrupted和interrupted联用)。
- 改正:
- 相应结果: 2秒后显示中断发生
-
- 关于interrupt(),java的jdk文档描述如下:API点击
- 线程的睡眠
- sleep() 定义在Thread.java中,而不是object。
- 作用:让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。
- sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;
- 在线程重新被唤醒时,它会由 “阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。
- 源码分析:
- 例子:
- 注意:Thread.sleep()方法由于中断而抛出异常,此时,它会清除中断标记。如果不加处理,那么在下一次循环开始时,就无法捕获这个中断,故在异常处理中,再次设置中断标记位。
- sleep() 与 wait()的比较
- wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。
- sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。
- 但是,wait()会释放对象的同步锁,而sleep()则不会释放锁。
- 例子:
- 相应结果:
t1:0 t1:1 t1:2 t1:3 t1:4 t1:5 t1:6 t1:7 t1:8 t1:9
t2:0 t2:1t2:2t2:3t2:4t2:5t2:6t2:7t2:8t2:9 - 结果表明:主线程main中启动了两个线程t1和t2。t1和t2在run()会引用同一个对象的同步锁,即synchronized(obj)。在t1运行过程中,虽然它会调用Thread.sleep(100);但是,t2是不会获取cpu执行权的。因为,t1并没有释放“obj所持有的同步锁”!
- 注释掉同步锁之后:ta、tb可以互相切换(因为之前sleep是和synchronized联用的,而现在没有持有锁,哪里来的释放)