线程停止指线程处理完任务之前停掉正在进行的操作。
一、停止线程的方法
使用退出标志,使线程正常退出,即当run方法完成后终止线程。
使用stop强行终止线程,但不推荐此方法,可能产生不可预料的后果。
使用interrupt方法中断线程。
二、判断线程是否是停止状态
方法一:this.interrupted() 测试当前线程是否已经中断,当前线程指运行this.interrupted()方法的线程。
方法二:this.isInterrupted()测试线程是否已经中断。
实例一:
public class MyThread extends Thread{ public void run() { super.run(); for(int i=0;i<75000;i++) { System.out.println("i=" + (i+1)); } } } public class App { public static void main(String[] args) { // TODO Auto-generated method stub try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(1000); thread.interrupt(); System.out.println("Is stop 1?=" + thread.interrupted()); System.out.println("Is stop 2?=" + thread.isInterrupted()); } catch(InterruptedException e) { e.printStackTrace(); } } }
Output:
i=72493
i=72494
i=72495
Is stop 1?=false
i=72496
i=72497
i=72498
i=72499
i=72500
i=72501
i=72502
i=72503
i=72504
i=72505
i=72506
i=72507
i=72508
i=72509
i=72510
i=72511
i=72512
i=72513
i=72514
i=72515
i=72516
i=72517
i=72518
i=72519
Is stop 2?=true
i=72520
Tips:
从结果来看,线程并未停下来。因为interrupted()测试当前线程是否已经中断。
测试代码:使main线程产生中断
public class App { public static void main(String[] args) { // TODO Auto-generated method stub try { Thread.currentThread().interrupt(); System.out.println("Is stop 1?=" + Thread.interrupted()); System.out.println("Is stop 2?=" + Thread.interrupted()); } catch(Exception e) { e.printStackTrace(); } } }
Output:
Is stop 1?=true
Is stop 2?=false
Tips:
方法的确判断出当前线程是停止状态,但由于线程中断状态会被interrupted()(这个方法是一个静态方法)清除,所以第二次调用返回了false。
而isInterrupted()方法并不会清除状态标识,所以多次调用不会有影响。
示例:判断线程是否是停止状态:
public class MyThread extends Thread{ public void run() { super.run(); for(int i=0;i<750000;i++) { if(this.interrupted()) { System.out.println("has stopped.So will quit."); break; } System.out.println("i=" + (i+1)); } } } public class App { 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!"); } }
Output:
i=170457
i=170458
i=170459
i=170460
end!
has stopped.So will quit.
示例:线程沉睡中被停止
public class App { 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{ public void run() { try { super.run(); System.out.println("run begin"); Thread.sleep(20000000); System.out.println("run end"); } catch(InterruptedException e) { System.out.println("be stopped and enter catch area when thread was sleeping." + this.isInterrupted()); e.printStackTrace(); } } }
Output:
run begin
end!
be stopped and enter catch area when thread was sleeping.false
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at P030.MyThread.run(MyThread.java:10)
Tips:
如果在sleep状态下停止某一线程,则会进入catch语句,并且会清除停止状态值,使之变成false。所以上面代码IsInterrupted()返回了false.
示例:测试先interrupt()后进入sleep()
public class MyThread extends Thread{ 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("be interruped!"); e.printStackTrace(); } } }public class App { public static void main(String[] args) { // TODO Auto-generated method stub MyThread thread = new MyThread(); thread.start(); thread.interrupt(); System.out.println("end!"); } }
Output:
i= 99994
i= 99995
i= 99996
i= 99997
i= 99998
i= 99999
i= 100000
run begin
be interruped!
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at P031.MyThread.run(MyThread.java:14)
Tips:
如果线程运行中被interrupt(),线程并不会立即停止,后续代码进入sleep()后,会抛出InterruptedException异常。
示例:stop()暴利停止线程
public class MyThread extends Thread{ private int i =0; public void run() { try{ while(true) { i++; System.out.println("i=" + i); Thread.sleep(1000); } } catch(InterruptedException e) { e.printStackTrace(); } } } public class App { public static void main(String[] args) { // TODO Auto-generated method stub try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(8000); thread.stop(); } catch(InterruptedException e) { e.printStackTrace(); } } }
Tips:
即被stop后立即停止。
示例:stop()与ThreadDeath异常
public class MyThread extends Thread{ public void run() { try { this.stop(); } catch(ThreadDeath e) { System.out.println("enter catch method"); } } }
示例:使用return停止线程
public class MyThread extends Thread{ public void run() { while(true) { if(this.isInterrupted()) { return; } } } }
Tips:相比于return,更建议使用抛异常的方法实现线程停止,因为catch可以处理异常信息,不至于代码出现多次return,造成代码污染。
-
疑问:
1、为什么线程interrupt()后,后续代码还在运行?
答:个人目前的理解是,当执行interrupt()方法后,线程只是被通知interrupt中断,改变线程interupted标识位。但是并不会立即杀死,具体过程,还需线程自己维护。(这也就解释了为什么Thread.Sleep()必须要加一个InterruptedException中断原因,因为在线程sleep状态下被中断会抛出异常,如果不在sleep状态,还会继续运行。如果有停止标识位,但是之前代码未处理,则会在sleep()中抛出。)