最近在看Java多线程编程核心技术,也一直忘的比看的快,所以就做个笔记吧,概念性的东西就懒得提了
~~~~~~~~~~~~~~~~~~~~~~~~~~~
停止一个线程意味着在线程处理完任务之前停掉正在做的操作,也就是放弃当前的操作.
停止一个线程可以使用Thread.stop()方法,但是最好不要用它,虽然确实可以停止一个正在运行的线程,但是这个方式是不安全的并且被废弃的
大多数停止一个线程的操作使用Thread.interrupt()方法,尽管方法的名称是"停止、终止"的意思,但这个方法不会终止一个正在运行的线程,还需要加入一个判断才可以完成线程的停止.
在Java中有以下3种方法可以终止正在运行的线程:
1.使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
2.使用stop方法强制终止线程,但是不推荐,因为stop和suspend及resume一样都是过期的方法,会产生不可预料的结果.
3. 使用interrupt方法中断线程
停止不了的线程
调用interrupt方法来停止线程,但是interrupt方法的效果并不想for+break那样马上停止循环,调用interrupt方法仅仅是在当前的线程中打了一个停止的标记,并不能真正的停止线程
public class MyThread extends Thread { @Override public void run() { super.run(); for (int i = 0; i < 500000; i++) { System.out.println("i=" + (i + 1)); } } }
public class Main { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(2000); thread.interrupt(); } catch (InterruptedException e) { System.out.println("main catch"); e.printStackTrace(); } } }从运行结果上看,调用interrupt方法并没有停止线程。如何停止线程呢?
判断线程是否停止
如何判断线程的状态是不是停止的,在Java API中,Thread类提供了两种方法.
1. this.interrupted(): 测试当前线程是否已经中断。
public static boolean interrupted() { return currentThread().isInterrupted(true); }
2. this.isInterrupted(): 测试线程是否已经中断
public boolean isInterrupted() { return isInterrupted(false); }
两个都调用的是一个底层的 native的方法
private native boolean isInterrupted(boolean ClearInterrupted);
native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。
那么这两个方法有什么区别呢? 先来看看this.interrupted()方法的解释:测试当前线程是否已经中断,当前线程是指运行this.interruped()方法的线程
public class MyThread extends Thread { @Override public void run() { super.run(); for (int i = 0; i < 500000; i++) { System.out.println("i=" + (i + 1)); } } }
public class Main { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(1000); thread.interrupt(); //Thread.currentThread().interrupt(); System.out.println("是否停止1?="+thread.interrupted()); System.out.println("是否停止2?="+thread.interrupted()); } catch (InterruptedException e) { System.out.println("main catch"); e.printStackTrace(); } System.out.println("end!"); } }
程序运行结果如下所示:
从控制台打印结果来看,线程并未停止,这也就证明的interrupted方法的解释,测试当前线程是否已经中断,这个当前线程是main,它从未中断过,所以结果是两个false
如何使main线程产生中断效果呢?
public class Main2 { public static void main(String[] args) { Thread.currentThread().interrupt(); System.out.println("是否停止1?=" + Thread.interrupted()); System.out.println("是否停止2?=" + Thread.interrupted()); System.out.println("end!"); } }
结果:
从上述结果来看,方法interrupted()的确判断出当前线程是否是停止状态,但为什么第二个值是false呢?官方文档对interrupted方法的解释:
测试当前线程是否已经中断。线程的中断状态由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。
文档已经解释得很详细,interrupted()方法具有清除状态的功能,所以第2次调用interrupted()方法返回的值是false。文档已经解释得很详细,interrupted()方法具有清除状态的功能,所以第2次调用interrupted()方法返回的值是false。
介绍完interrupted()方法后再来看一下isInterrupted()方法,声明如下:介绍完interrupted()方法后再来看一下isInterrupted()方法
public class Main3 { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(1000); thread.interrupt(); System.out.println("是否停止1?="+thread.isInterrupted()); System.out.println("是否停止2?="+thread.isInterrupted()); } catch (InterruptedException e) { System.out.println("main catch"); e.printStackTrace(); } System.out.println("end!"); } }
运行结果如下:
从结果中可以看到,方法isInterrupted()并未清除撞他标志,所以打印了两个true.
最后,再来看一下这两个方法的解释。
1. this.interrupted():测试当前线程是否已经中断状态,执行后具有将状态标志清除为false的功能。
2. this.isInterrupted():测试线程Thread对象是否已经是中断状态,但不清除状态标志.
能停止的线程-异常法
public class MyThread extends Thread { @Override public void run() { super.run(); for (int i = 0; i < 500000; i++) { if (this.interrupted()) { System.out.println("已经是停止状态了!我要退出了!"); break; } System.out.println("i=" + (i + 1)); } } }
public class Run { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(2000); thread.interrupt(); } catch (InterruptedException e) { System.out.println("main catch"); e.printStackTrace(); } System.out.println("end!"); } }
public class MyThread extends Thread { @Override public void run() { super.run(); for (int i = 0; i < 500000; i++) { if (this.interrupted()) { System.out.println("已经是停止状态了!我要退出了!"); break; } System.out.println("i=" + (i + 1)); } System.out.println("我被输出,如果此代码是for又继续运行,线程并未停止!"); } }
public class Run { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(2000); thread.interrupt(); } catch (InterruptedException e) { System.out.println("main catch"); e.printStackTrace(); } System.out.println("end!"); } }
public class MyThread extends Thread { @Override public void run() { super.run(); try { for (int i = 0; i < 500000; i++) { if (this.interrupted()) { System.out.println("已经是停止状态了!我要退出了!"); throw new InterruptedException(); } System.out.println("i=" + (i + 1)); } System.out.println("我在for下面"); } catch (InterruptedException e) { System.out.println("进MyThread.java类run方法中的catch了!"); e.printStackTrace(); } } }
在沉睡中停止
public class MyThread extends Thread { @Override public void run() { super.run(); try { System.out.println("run begin"); Thread.sleep(200000); System.out.println("run end"); } catch (InterruptedException e) { System.out.println("在沉睡中被停止!进入catch!"+this.isInterrupted()); e.printStackTrace(); } } }
public class Run { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(200); thread.interrupt(); } catch (InterruptedException e) { System.out.println("main catch"); e.printStackTrace(); } System.out.println("end!"); } }
public class MyThread extends Thread { @Override public void run() { super.run(); try { for(int i=0;i<100000;i++){ System.out.println("i="+(i+1)); } System.out.println("run begin"); Thread.sleep(200000); System.out.println("run end"); } catch (InterruptedException e) { System.out.println("先停止,再遇到了sleep!进入catch!"); e.printStackTrace(); } } }
public class Run { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); thread.interrupt(); System.out.println("end!"); } }
能停止的线程-暴力停止
public class MyThread extends Thread { private int i = 0; @Override public void run() { try { while (true) { i++; System.out.println("i=" + i); Thread.sleep(1000); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
public class Run { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(8000); thread.stop(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
使用return停止线程
public class MyThread extends Thread { @Override public void run() { while (true) { if (this.isInterrupted()) { System.out.println("停止了..."); return; } System.out.println("timer=" + System.currentTimeMillis()); } } }
public class Run { public static void main(String[] args) throws InterruptedException { MyThread t=new MyThread(); t.start(); Thread.sleep(2000); t.interrupt(); } }
不过还是建议使用 抛异常 的方式来实现线程的停止,因为在catch块中可以对异常信息进行相关的处理,而且使用异常能更好的 更方便的控制程序的运行流程,不至于代码中出现很多个return;造成污染