1.通过设置标志位方式停止线程
如下面代码所示,通过将标志为设置为flag可以停止线程。
class myThread extends Thread { boolean flag = true; public void run() { while(flag) { System.out.println("一直执行"); } } public void set() { flag = false; } } class HighConcurrency { public static void main(String[] args) throws InterruptedException { myThread t1 = new myThread(); t1.start(); Thread.sleep(10); //这边要加一个睡眠,否则可能会导致先执行t1.set()方法 for(int i=0;i<1000;i++) { if(i==50) { t1.set(); } } } }
缺点:当线程中sleep()方法,或者wait()调用的时候,IO阻塞(例如使用readLine()方法等待读取一个信息),这时候线程这种方法就不行了
2.通过中断方式退出线程
class MyThread extends Thread { @Override public void run() { super.run(); try { for (int i = 0; i < 500000; i++) { if (Thread.interrupted()) { //静态方法 System.out.println("已经是停止状态了!我要退出了!"); throw new InterruptedException(); //在收到中中断标志后,进入catch语句 } System.out.println("i=" + (i + 1)); } System.out.println("我在for下面"); //这段代码没有执行 } catch (InterruptedException e) { System.out.println("进MyThread.java类run方法中的catch了!"); e.printStackTrace(); } } } public class HighConcurrency { 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!"); } }代码执行结果:
i=238860 i=238861 i=238862 i=238863 已经是停止状态了!我要退出了! end! 进MyThread.java类run方法中的catch了! java.lang.InterruptedException at com.High.Concurrency.MyThread.run(HighConcurrency.java:154)
3.线程在sleep()状态遇到中断会抛出InterruptException
说明:中断后,sleep()方法进入中断,注意此时if(Thread.currentThread().isInterrupt())并没有收到信号,因为是在sleep中断时进入catch语句的,所以在catch语句中再次中断当前线程,在if(Thread.currentThread().isInterrupt())语句中做后续的处理,保证数据的一致性和完整性。
public class HighConcurrency { public static void main(String args[]) throws InterruptedException { Thread thread = new Thread() { @Override public void run() { while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println("收到中断信号,停止该线程!"); break; } try { Thread.sleep(600); } catch (InterruptedException e) { //在这里做些后续处理保证数据的一致性和完整性 e.printStackTrace(); Thread.currentThread().interrupt(); //或者使用this.interrupt() } System.out.println("Running!"); Thread.yield(); } } }; thread.start(); Thread.sleep(2000); thread.interrupt();//进行中断操作 } }
说明:run()方法中使用Thread.currentThread().interrupt()和this.interrupt()都是可以的,这里的this其实就是指的是调用该方法的对象,也就是thread线程,如果使用打印Thread.current().hashCode()和this.hashCode()会发现两者相同。
4.与线程中断的三个方法的说明:
public void interrupt() //中断线程
public boolean isInterrupted() //判断是否被中断
public static boolean interrupted() //判断是否被中断,并清除当前中断状态,这是一个静态方法
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 HighConcurrency { public static void main(String[] args) { Thread.currentThread().interrupt(); //中断后会清除中断标志 System.out.println("是否停止1?=" + Thread.interrupted()); //返回true 注意这是静态方法 System.out.println("是否停止2?=" + Thread.interrupted()); //返回false,注意因为上面的interrupt自动清除了标志位 Thread.currentThread().interrupt(); //中断后并未清除中断标志 System.out.println("是否停止1?=" + Thread.currentThread().isInterrupted()); //返回true 注意这不是静态方法,获取当前线程调用 System.out.println("是否停止2?=" + Thread.currentThread().isInterrupted()); //返回true System.out.println("end!"); } }
是否停止1?=true 是否停止2?=false 是否停止1?=true 是否停止2?=true end!