并发编程大师系列之:线程的定义和中断 interrupt
Posted zhangjianbing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程大师系列之:线程的定义和中断 interrupt相关的知识,希望对你有一定的参考价值。
1.启动线程的三种方式:
1.1继承Thread类
public static class UseThread extends Thread { public void run() { System.out.println("thread run 执行!"); } }
启动线程:
UseThread ut = new UseThread(); ut.start();
1.2实现Runable接口
public static class UseRun implements Runnable { @Override public void run() { System.out.println("runable run 执行!"); } }
启动线程
UseRun ur = new UseRun(); new Thread(ur).start();
1.3实现Callable接口
public static class UseCall implements Callable<String> { @Override public String call() throws Exception { return "callable call 执行!"; } }
启动线程
它是有返回值的,需要用FutureTask来包装,如:
UseCall uc = new UseCall(); FutureTask<String> ft = new FutureTask<>(uc); new Tread(ft).start(); System.out.println(ft.get());
返回值需要用Future的get方法来获取。 执行结果:
callable call 执行!
2.使用interrupt来中断线程
先看一段代码
public class InterruptTest01 { public static class m1 implements Runnable { public void run() { try { System.out.println("in run() - 睡眠20秒"); Thread.sleep(20000); System.out.println("in run() - 线程唤醒"); } catch (Exception e) { System.out.println("in run() - 线程睡眠中被打断了"); // 如果没有return,线程不会实际被中断,它会继续打印下面的信息 System.out.println("t线程sleep中被打断后中断标志位状态:" + Thread.interrupted()); return; } System.out.println("in run() - 线程正常的消亡了"); } } public static void main(String[] args) { m1 si = new m1(); Thread t = new Thread(si); // 开启t线程 t.start(); System.out.println("调用interrupt方法前,t线程的中断状态:" + t.isInterrupted()); try { // 仅仅是做标记 t.interrupt(); System.out.println("调用interrupt方法后,t线程的中断状态:" + t.isInterrupted()); // 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间 Thread.sleep(2000); } catch (InterruptedException e) { System.err.println("主线程catch块出问题了"); } System.out.println("in main() - 主线程终止了"); } }
运行的结果:
调用interrupt方法前,t线程的中断状态:false 调用interrupt方法后,t线程的中断状态:true in run() - 睡眠20秒 in run() - 线程睡眠中被打断了 t线程sleep中被打断后中断标志位状态:false in main() - 主线程终止了
分析:
分析:Thread.sleep(2000)这个方法需放在interrupt方法之后,如果放在之前,会出现中断标志位全为false的情况。如果只是单纯的调用interrupt()方法,线程并没有实际被中断,会继续往下执行。
比如这样:
public class InterruptTest01 { public static class m1 implements Runnable { public void run() { while (true){ System.out.println("我是不会中断的了"); } } } public static void main(String[] args) { try { m1 si = new m1(); Thread t = new Thread(si); // 开启t线程 t.start(); System.out.println("调用interrupt方法前,t线程的中断状态:" + t.isInterrupted()); // 仅仅是做标记 t.interrupt(); System.out.println("调用interrupt方法后,t线程的中断状态:" + t.isInterrupted()); // 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间 Thread.sleep(2000); } catch (InterruptedException e) { System.err.println("主线程catch块出问题了"); } System.out.println("in main() - 主线程终止了"); } }
它的运行结果就是自旋,应当在run方法中加上中断标志位的判断,如下:
public static class m1 implements Runnable { public void run() { while (true){ if(Thread.interrupted()){ System.out.println("我竟然中断了"); return; } System.out.println("我是不会中断的了"); } } }
再次运行的结果:
调用interrupt方法前,t线程的中断状态:false 调用interrupt方法后,t线程的中断状态:true 我竟然中断了 in main() - 主线程终止了
3.待决中断
意思就是:如果线程在调用sleep()方法前被中断,那么该中断称为待决中断,它会在刚调用sleep()方法时,立即抛出InterruptedException异常。
如下:
public class PendingInterruptTest { public static void main(String[] args) { Thread.currentThread().interrupt(); // 获取当前时间 long startTime = System.currentTimeMillis(); try { Thread.sleep(2000); System.out.println("主线程没有被打断"); } catch (InterruptedException x) { System.out.println("主线程被打断,进入catch块"); } // 计算中间代码执行的时间 System.out.println("时间差 =" + (System.currentTimeMillis() - startTime)); } }
运行代码的结果:
主线程被打断,进入catch块
时间差 =1
4.interrupted和isInterrupted的区别?
首先看一段代码
public class InterruptTest01 { public static class m1 implements Runnable { public void run() { System.out.println("我是不会中断的了"); } } public static void main(String[] args) { try { m1 si = new m1(); Thread t = new Thread(si); // 开启t线程 t.start(); System.out.println("调用interrupt方法前0,t线程的中断状态:" + t.interrupted()); t.interrupt(); System.out.println("调用interrupt方法后1,t线程的中断状态:" + t.interrupted()); System.out.println("调用interrupt方法后2,t线程的中断状态:" + t.interrupted()); // 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间 Thread.sleep(2000); } catch (InterruptedException e) { System.err.println("主线程catch块出问题了"); } System.out.println("in main() - 主线程终止了"); } }
运行的结果为:
调用interrupt方法前0,t线程的中断状态:false 调用interrupt方法后1,t线程的中断状态:false 调用interrupt方法后2,t线程的中断状态:false 我是不会中断的了 in main() - 主线程终止了
分析:
结果竟然都是false,可见thread 线程并没有停止,而且调用 thread.interrupted() 结果是两个 false 表示线程一直在运行过程中。官方解释:当前线程是指运行 this.interrupted() 方法的线程 。也就是说,当前线程并不是 t,并不是因为 t 调用了 interrupted() 方法就是当前线程。当前线程一直是 main 线程,它从未中断过,所以打印结果就是两个 false。
改变一下代码:
public class InterruptTest01 { public static class m1 implements Runnable { public void run() { System.out.println("我是不会中断的了"); } } public static void main(String[] args) { try { m1 si = new m1(); Thread t = new Thread(si); // 开启t线程 t.start(); System.out.println("调用interrupt方法前0,t线程的中断状态:" + Thread.interrupted()); Thread.currentThread().interrupt(); System.out.println("调用interrupt方法后1,t线程的中断状态:" + Thread.interrupted()); System.out.println("调用interrupt方法后2,t线程的中断状态:" + Thread.interrupted()); // 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间 Thread.sleep(2000); } catch (InterruptedException e) { System.err.println("主线程catch块出问题了"); } System.out.println("in main() - 主线程终止了"); } }
结果:
调用interrupt方法前0,t线程的中断状态:false 调用interrupt方法后1,t线程的中断状态:true 调用interrupt方法后2,t线程的中断状态:false 我是不会中断的了 in main() - 主线程终止了
分析:
从上述结果中可以看出,方法 interrupted() 的确判断出当前线程是否已经停止,但是为什么第 2 个布尔值是 false 呢?文档中说的很详细,interrupted() 方法具有清除状态的功能,所以第二次的时候返回值是 false。
isInterrupt()方法代码
public static void main(String[] args) { try { Thread t = Thread.currentThread(); System.out.println("调用interrupt方法前0,t线程的中断状态:" + t.isInterrupted()); t.interrupt(); System.out.println("调用interrupt方法后1,t线程的中断状态:" + t.isInterrupted()); System.out.println("调用interrupt方法后2,t线程的中断状态:" + t.isInterrupted()); // 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间 Thread.sleep(2000); System.out.println("还在输出吗?"); } catch (InterruptedException e) { System.err.println("主线程catch块出问题了"); } System.out.println("in main() - 主线程终止了"); }
结果:
调用interrupt方法前0,t线程的中断状态:false 主线程catch块出问题了 调用interrupt方法后1,t线程的中断状态:true 调用interrupt方法后2,t线程的中断状态:true in main() - 主线程终止了
分析:
线程一旦被中断,isInterrupted()方法便会返回true,而一旦sleep()方法抛出异常,它将清空中断标志,此时isInterrupted()方法将返回false
总结以上:
总结:interrupted():测试 当前线程 是否已经是中断状态,执行后具有清除状态功能。isInterrupted():测试线程 Thread 对象 是否已经是中断状态,但不清除状态标志。
以上是关于并发编程大师系列之:线程的定义和中断 interrupt的主要内容,如果未能解决你的问题,请参考以下文章