一.
为什么会讲述图解,是因为目前DOS给出的一些结果有写颠覆了原有的思想体系。多线程在执行时,cpu切换这执行,不同的内容交叉着出现。但是之前我们讲,一个函数只有执行完了才会弹栈,没执行完不会弹栈。现在通过图解来解释这一切。
以上面的截图来研究图解,我们只研究栈,其他的不做探讨。
以前的内存图解是,main方法进栈,然后涉及调用的方法依次进栈,每执行完一个,出栈一个。最后main方法出栈,井然有序,但是在多线程这里就不能这样操作了。
现在运行方式变了,你只要开启了一条执行路径,它就有了一条单独的执行路径。以前理解为一条马路的话,现在是三条。
主线程只要一开,主线程路径就已经出现了,因为它在调用,或者去执行主函数(这是主线程路径)。在主函数里的代码执行过程中,创建了两个线程(创建和使用是两回事,可以创建后不用)。当主线程读到d1.start()时,就开启了一条路径,这时就多了一条路径。第一条执行路径里的内容是main,第二条执行路径里的内容是run。当主线程继续执行d2.start()的时候,又开启了一条路径,这路径执行的内容还是run。这就相当于它们里面有着自己独立的空间。
main如果调用了调用了其他的方法,就在main的栈区里加栈,就是说你只要是主线程路径上的,就在主线程栈区里加栈,然后进栈弹栈。如果是run()方法调用其他方法的话,就在run栈区里进栈弹栈。同时还给这些线程起了名字,main,Thread-0,Thread-1。每个run方法都有自己所属的线程的栈区。
同时一点都不冲突是因为,每个run方法里面都有一个变量叫x,run方法里有for循环语句的局部变量,(我是觉着x的存在和多个run之间冲不冲突没有什么关系。)
这有三个任务在这执行,一旦有一个任务这里面的代码执行完了,这个任务就结束了。如果是线程0,它调用了一个haha方法,haha方法就要进栈,进的线程0的栈。进了之后,执行结束就出栈了。如果run方法也执行完了,这个线程所执行的任务也就结束了,它这个地方就释放了,这条路径就不需要了。因为线程是要执行代码的,它代
码结束了,线程就没意义存在了。
有没有存在这样一种情况,这三个任务同时在执行,cpu在这三者之间切换。有趣的来了,main线程先结束了,虚拟机结束没?没有,只要还有正在运行的线程,它就会存在。只能说主线程先结束了。
现在再更加扩展的讲述一下,
下面的thread-0和thread-1还在执行,
主线程执行到4/0这句话,就出现了异常。接着这个异常就被抛出了给了jvm默认处理,最后打印在DOS控制台上。输出语句的下面for语句就没再执行,
其他的还在执行,main线程出现了问题,和其他线程没有关系。
(这里甚至打印异常都是分开来的)
多试了几次之后,终于出现了打印的异常信息集中在一起的情况
(但还是有一个run内容出现)
在打印结果的第一行,Exception in thread “main”是之前没讲过的,之前讲述的都是java.lang.ArithmeticException……多出来的第一句意思是异常在线程名为main的里面发生。
我们现在随便编译运行一个不存在的haha
结果显示在主线程中发生,都是一个意思。
现在再进一步地改进,
也就是对run方法的线程也设置成出现异常。
整个编译运行的结果如下,
DOS结果报告了在三个线程上都出现了异常,出现异常后,该线程里的内容就停止运行了。
谁发生问题,谁结束,其他的不影响。