一 . 线程打断
一个线程运行之后,我们就无法控制这个线程的具体的运行情况了.
在一个特殊的情况下,我们需要终结一个无线循环的线程任务或者是一个长时间运行的线程任务该怎么办?
在jdk之中,Thread类之中的很多方法都被废弃,原因就是这些方法是直接杀死线程,而线程获取的资源还可能未被释放.
现在还剩下一个interrupt()方法可以帮助我们实现这个功能.
二 . 线程打断的特性
private static class Interrupt extends Thread{ @Override public void run() { for(;;) { System.out.println("thread is running"); } } } public static void main(String[] args) throws InterruptedException { // 从这个例子之中,我们知道调用一个线程的interrupt方法不会直接终结线程的运行. Interrupt thread = new Interrupt(); thread.start(); TimeUnit.SECONDS.sleep(2); thread.interrupt(); }
private static class Interrupt extends Thread{ @Override public void run() { while(!Thread.currentThread().isInterrupted()) { System.out.println("thread is running"); } } } public static void main(String[] args) throws InterruptedException { /** * 当一个线程被打断的时候,线程的状态标记为自己被打断了.我们可以通过这个标识来确定这个线程是否收到打断的信号. */ Interrupt thread = new Interrupt(); thread.start(); TimeUnit.SECONDS.sleep(2); thread.interrupt(); }
private static class Interrupt extends Thread{ @Override public void run() { while(!Thread.currentThread().isInterrupted()) { System.out.println("thread is running"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); //Thread.currentThread().interrupt(); // 上面的代码,我们主动打断自己,就能完成线程的终结. } } } } public static void main(String[] args) throws InterruptedException { /** * 当一个线程由于调用了可以抛出InterruptedException异常的方法而陷入阻塞状态的时候, * 此时一旦线程被打断,就会抛出一个InterruptedException异常. * 并且线程的被打断的标记会被重置. * 这个时候,我们如果想要完成线程的终结,就需要手动进行异常处理. 就像上面,我们主动打断线程自己. */ Interrupt thread = new Interrupt(); thread.start(); TimeUnit.SECONDS.sleep(2); thread.interrupt(); }
三 . 为什么不使用标记符号完成线程的终结
/**
* 为什么不建议使用状态标记完成线程的终结操作:
* 一旦一个线程处于阻塞状态,它是无法及时的处理状态标记修改的响应的.
* 如果我们想要打断一个线程,尽量还是使用interrupt来完成.
*/
四 . 使用守护线程终结线程
我们知道守护线程有一个特性,那就是守护线程的生命周期取决于其他的非守护线程.
Thread thread = new Thread(new Runnable() { @Override public void run() { for(;;) System.out.println("我是守护线程,帮助老大完成任务"); } }); thread.setDaemon(true); thread.start(); //主线程 Thread.sleep(3000); System.out.println("main thread ending ...");
上面的例子之中,我们使用daemon的方式终结了一个线程任务.
当主线程完成了任务,子线程就没有必要存在了,比如子线程在做心跳检测.
相比较而言,我们使用daemon来完成线程的终结还是比较好的.