• JAVA-初步认识-第十二章-多线程运行图解


    一.

    为什么会讲述图解,是因为目前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结果报告了在三个线程上都出现了异常,出现异常后,该线程里的内容就停止运行了。

    谁发生问题,谁结束,其他的不影响。

  • 相关阅读:
    supervisord + docker run = web页面管理运行的docker
    docker之Dockerfile实践用dockerfile构建nginx环境
    Dockerfile文件详解
    【docker】CMD ENTRYPOINT 区别 终极解读!
    golang html/template
    网络连接带宽的理论最大值
    Queue length 和 Queue depth 的区别
    .tar.gz 文件和 .tar.xz 文件的区别
    如何同时在Isilon的所有网卡上抓取网络包?
    Reimage Isilon cluster,结果忘记了修改管理口的netmask,怎么办?
  • 原文地址:https://www.cnblogs.com/wsw-bk/p/8051462.html
Copyright © 2020-2023  润新知