一、概述
一个多个线程在执行的Java程序,只有当其全部的线程执行结束时(更具体的说,是所有非守护线程结束或者某个线程调用System.exit()方法的时候),它才会结束运行。
中断(Interrupt)一个线程意味着在该线程完成任务之前停止其正在进行的一切,有效地中止其当前的操作。线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于这个程序。虽然初次看来它可能显得简单,但是,你必须进行一些预警以实现期望的结果。
二、实现
案例1:真正地中断一个线程最好的,最受推荐的方式是,使用共享变量(shared variable)发出信号,告诉线程必须停止正在运行的任务。线程必须周期性的核查这一变量(尤其在冗余操作期间),然后有秩序地中止任务。
public class ThreadInterruptTest extends Thread { volatile boolean stop = false; public static void main( String args[] ) throws Exception { ThreadInterruptTest thread = new ThreadInterruptTest(); System.out.println( "Starting thread..." ); thread.start(); Thread.sleep(3000); System.out.println( "Asking thread to stop..." ); thread.stop = true; Thread.sleep(2000); System.out.println( "Stopping application..." ); } public void run() { while ( !stop ) { System.out.println( "Thread is running..." ); long time = System.currentTimeMillis(); while ( (System.currentTimeMillis()-time < 1000) && (!stop) ) { } } System.out.println( "Thread exiting under request..." ); } }
//console结果: -> 中断后,有顺序的 退出Starting thread...Thread is running...Thread is running...Thread is running...Thread is running...Asking thread to stop...Thread exiting under request...Stopping application...
案例二:interrupt() 使用
public class Consumer implements Runnable{ public void run() { try{ System.out.println("in run() - about to sleep for 20 seconds"); Thread.sleep(20000); System.out.println("in run() - woke up"); }catch(InterruptedException e){ System.out.println("in run() - interrupted while sleeping"); //处理完中断异常后,返回到run()方法人口, //如果没有return,线程不会实际被中断,它会继续打印下面的信息 return; } System.out.println("in run() - leaving normally"); }}
public class TestInterrupt { public static void main(String[] args) { Consumer si = new Consumer(); Thread t = new Thread(si); t.start(); //主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间 try { Thread.sleep(2000); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println("in main() - interrupting other thread"); //中断线程t t.interrupt(); System.out.println("in main() - leaving"); }}
//console结果:in run() - about to sleep for 20 secondsin main() - interrupting other threadin main() - leavingin run() - interrupted while sleepingin run() - leaving normally
说明:主线程启动新线程后,自身休眠2秒钟,允许新线程获得运行时间。新线程打印信息“about to sleep for 20 seconds”后,继而休眠20秒钟,但是大约2秒钟后,main线程通知新线程中断,那么新线程的20秒的休眠将被打断,从而抛出InterruptException异常,执行跳转到catch块,打印出“interrupted while sleeping”信息,并立即从run()方法返回,然后消亡,而不会打印出catch块后面的“leaving normally”信息。
请注意:由于不确定的线程规划,上图运行结果的后两行可能顺序相反,这取决于主线程和新线程哪个先消亡。但前两行信息的顺序必定如上图所示。另外,如果将catch块中的return语句注释掉,则线程在抛出异常后,会继续往下执行,而不会被中断,从而会打印出”leaving normally“信息。
案例三:interrupt() 使用
public class TestRunnable implements Runnable{ public void run() { boolean isRunning = true; while(isRunning){ System.out.println("Thread is running..."); long start = System.currentTimeMillis(); if(System.currentTimeMillis() - start < 1000){ } try { Thread.sleep(5000); } catch (InterruptedException e) { isRunning = false; // 若去掉 则 run 相当于没有中断掉,接着进行 System.out.println("Run Thread is end.."); } } }}
public class ThreadDemo { public static void main(String[] args) { TestRunnable testRunnable = new TestRunnable(); Thread thread = new Thread(testRunnable); thread.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); System.out.println("main Thread is end.."); }}/** console结果: *Thread is running... *main Thread is end.. *Run Thread is end.. */