🍇3.3查看Java线程内部基础属性
在我们下载好的jdk文件打开bin文件
找到这个文件双击
点击我们执行的文件
点击链接后,弹出这个页面,点击不安全链接
点击右上角线程这样我们就可以看到Java线程的一些属性
🍇3.4线程的中断
方法一:
public class deom9 { private static boolean quite = false; public static void main(String[] args) throws InterruptedException { Thread thread9 = new Thread(new Runnable() { @Override public void run() { //我们让每次相隔1秒打印一次 while (!quite) { System.out.println("一个不起眼的线程"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }); thread9.start(); //main和线程一起执行,这样我们可以先限制5秒这样就可以先打印5次在终止了 Thread.sleep(5000); quite = true; } }
但是该方法是不够严谨的,有些场景可能达不到预期的效果,最优的做法就是调整线程对象或者线程类中的自带标志位
优化版本
public class demo10 { public static void main(String[] args) throws InterruptedException { Thread thread10 = new Thread(()->{ while (!Thread.interrupted()) { System.out.println("一个不起眼的线程"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread10.start(); //休眠5秒 Thread.sleep(5000); //使用interrupt方法修改线程标志位,使其中断 thread10.interrupt(); } }
我看到当我们进行5秒后的中断指令后发现线程还在继续执行,抛出一个InterruptedException异常后,线程没有中断,而是继续运行,原因是interrupt方法遇到因为调用 wait/join/sleep 等方法而阻塞的线程时会使sleep等方法抛出异常,并且中断标志位不会修改为true,这时我们的catch语句里面值输出了异常信息并没有去中断异常,所以我们需要在catch语句中加上线程结束的收尾工作代码和退出任务循环的break语句就可以了。
这样我们就可以看到我们已经成功中断线程执行了
方法二:
首先使用currentThread方法获取线程对象,然后再调用该对象中的isterrupted方法获取该对象的中断标志位代替我们自己所写的isQuit标志位,然后等该线程运行一段时间后使用interrupt方法改变标志位,中断线程,写出如下代码,看看能不能达到预期效果:
我们在实际使用中建议使用方法二
public class demo10 { public static void main(String[] args) throws InterruptedException { Thread thread10 = new Thread(()->{ while (!Thread.currentThread().interrupted()) { System.out.println("一个不起眼的线程"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("线程终止"); break; } } }); thread10.start(); //休眠5秒 Thread.sleep(5000); //使用interrupt方法修改线程标志位,使其中断 thread10.interrupt(); } }
🍇3.5线程等待
像上面的计算自增20亿次的例子就需要线程join方法,main线程需要等两个线程运行完毕后才能计算计算结束时的时间戳。
我们来假设几个线程,线程A表示调用join方法的线程,线程B表示join方法来自B线程对象,那么在A线程使用B.join方法,那就是A线程等待B线程结束
// join 效果就是等待线程结束. t1.join 就是让 main 线程等待 t1 结束. t2.join 让 main 线程等待 t2 结束. t1.join(); t2.join();
🍇3.6run方法与start方法的区别(面试问题)
当我们调用run方法就是单纯地调用了Thread对象中的一个重写普通方法而已,并没有创建一个新线程来执行run方法,而是通过main线程来执行的run方法,而使用start方法,会创建一个新线程并执行run方法。
注意:只有在执行线程的start方法时才是真正的完成创建线程