1.停止线程
停止线程是多线程开发很重要的技术点,掌握此技术可以对线程的停止惊醒有效的处理。
停止一个线程可以使用Thread.stop()方法,但最好不要使用它,这个方法是不安全的。
大多数停止一个线程使用的是Thread.interrupt()方法,尽管方法的名称是“停止,中止”,但这个方法不会终止一个正在运行的线程,还需要加入一个判断才可以完成线程的停止。
停止不了的线程
本例将调用inrerupt()方法来停止线程,但interrupt方法的使用效果并不像for+break那样,马上停止循环。调用interrupt方法仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程。
判断线程是否是停止状态
Thread中
this.interrupted()测试当前线程是否已经中断,执行后具有将状态标识置为false的功能。
this.isInterrupted()测试线程Thread是否已经是中断状态,但不清除状态标识。
先来测试interrupted();
类Run.java中虽然是在Thread对象上调用一下代码:
thread.interrupt();
来停止thread对象所代表的线程,在后面又使用
来判断thread对象所代表的线程是否停止,但从控制台打印的结果来看并未停止,这也就证明了interrupted方法测试的是当前线程是否已经中断。这个当前线程就是main,它从未中断过,所以打印的是两个false;
再来看看IsInterrupted()方法
2、interrupted 和 isInterrupted
1 |
public static boolean interrupted () { |
2 |
return currentThread().isInterrupted( true ); |
3 |
} |
1 |
public boolean isInterrupted () { |
2 |
return isInterrupted( false ); |
3 |
} |
- interrupted 是作用于当前线程,isInterrupted 是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程。例如我们可以在A线程中去调用B线程对象的isInterrupted方法。)
- 这两个方法最终都会调用同一个方法,只不过参数一个是true,一个是false;
1 |
private native boolean isInterrupted( boolean ClearInterrupted); |
如果这个参数为true,说明返回线程的状态位后,要清掉原来的状态位(恢复成原来情况)。这个参数为false,就是直接返回线程的状态位。
这两个方法很好区分,只有当前线程才能清除自己的中断位(对应interrupted()方法)
是不是这样理解呢,
Thread.currentThread().interrupt(); 这个用于清除中断状态,这样下次调用Thread.interrupted()方法时就会一直返回为false,因为中断标志已经被恢复了。
而调用isInterrupted 只是简单的查询中断状态,不会对状态进行修改。
interrupted是静态方法,返回的是当前线程的中断状态。例如,如果当前线程被中断(没有抛出中断异常,否则中断状态就会被清除),你调用interrupted方法,第一次会返回true。然后,当前线程的中断状态被方法内部清除了。第二次调用时就会返回false。如果你刚开始一直调用isInterrupted,则会一直返回true,除非中间线程的中断状态被其他操作清除了。
能停止的线程——一异常法
异常中断
抛出InterruptedException()异常,然后捕捉异常
在沉睡中中止
如果线程在sleep()状态下停止线程会是什么效果呢?
线程被终止,“run end“没有打印出来
前一个实验室先Sleep然后interrupt()停止,与之想法的操作在学习线程也要注意
先interrupt然乎再sleep
当再主线程中调用了interrup后,遇到sleep会触发inerruptExceptiony异常。
暴力停止
使用stop()方法停止线程是非常暴力的。
调用stop()方法会抛出ThreadDeath异常,但在通常的情况下,此异常不需要显示的捕捉。
使用stop()释放锁会给数据造成不一致性的结果。所以不要使用stop();
使用return停止线程
使用interrupt()与return结合使用也能实现停止线程的效果
2.暂停线程
暂停线程以为着此线程可以恢复运行。在java多线程中,可以使用supsend()方法暂停线程,使用resumen()方法来回复线程的执行
suspend和resume方法的使用
suspend()和resume()方法的缺点——独占
在使用suspend和resume方法时,如果使用不当,极易造成公共的同步对象的独占,使其他线程无法访问公共同步对象。
supsend作废的原因DEMO
出现这样情况的原因是,当程序运行到println()方法时,同步所未被释放。这导致当前PrintStream对象println方法一直呈“”暂停状态。
所以main()方法中的代码无法打印。
suspend和resume方法的缺点——不同步
yield方法
yield()方法的作用是放弃当前的CPU资源,将它让给其它的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CpU时间片。