上篇中介绍了如何启动一个线程,通过调用start()方法才能创建并使用新线程,并且这个start()是非阻塞的,调用之后立马就返回的,实际上它是线程生命周期环节中的一种,所以这里阐述一下线程的一个完整生命周期,里面涉及的一些状态目前还未学习到,没有关系,先有个全局观,之后都会涉及到滴。

线程的生命周期:

①、new状态:

当新建一个Thread对象时,此时的状态就是new状态:

注:这时线程还没有创建。

②、runnable状态:

当执行了Thread.start()方法之后,并不代表线程立即就能够执行,还得由CPU调度,所以此时是一个Runnable状态,也就是可以执行的状态。

③、running状态:

当CPU分配给了可运行的线程执行权时,这时线程就真正处理运行状态了:

④、blocked状态:

当运行的线程调用了wait、sleep、锁时,会从running状态变为blocked状态:

当blocked状态结束之后,比如sleep结束了,这时它不是直接就回到了running状态了,而是先回到runnable状态:

另外在running状态的线程可能被cpu把执行权切走了,也就是调度给其它线程了,这时running状态就会回到runnable状态了:

⑤、teminated状态:

最后就是线程结束状态,有几个状态都可能到线程结束状态:

  • running正在运行的线程正常执行完,也就到了结束状态了:
  • 在blocked状态,比如wait状态被打断了,也有可能进入结束状态:
  • 在runnable状态中,如果出现一些异外情况线程死了,也有可能进入结束状态:

start()源码简单剖析:

先来看一下start()在JDK官方文档的说明:

如何理解,结合代码,这里不是用上篇中的代码为例:

所以这两个线程是:main启动线程、Read-Thread新建的线程。

接着再看文档描述:

那如果调用两次呢?

如文档描述所示,抛异常了。

那有个疑问:为啥不直接调run方法,而非得通过start()方法去启动呢?

下面试试直接调run方法:

下面来看看start()方法内部到底做了哪些事情呢?

其实这种设计技巧是一种模板方法,下面来编写一个模板方法来体会Thread的start()设计的思想:

涉及到的设计模式:

另外正常的模板方法是需要将定声明为final类型的:

当然Thread的start()方法木有将它声明为final类型:

这样子类就可以对它进行复写:

跟严格意义上的模板方法还是有些区别,不过可以思想是类似的。

线程概念总结:

这是第二篇对线程基础的巩固,涉及到了一些概念,好的学习方法是要善于总结的,所以这里对学的知识总结一下:

①、java应用程序的main函数是一个线程,是被JVM启动时调用的,线程的名字叫main。

②、实现一个线程,必须创建Thread实例,override run方法,并且调用start方法。

③、在JVM启动后,实际上有多个线程,但是至少有一个非守护进程。

④、当你调用一个线程start方法之后,此时至少有两个线程:一个是调用你的线程,另一个是执行run方法的线程【新创建的线程】。

⑤、线程的生命周期分为:new、runnable、running、blocked、teminated。

转载于:https://www.cnblogs.com/webor2006/p/7683988.html

java线程基础巩固---线程生命周期以及start方法源码剖析相关推荐

  1. 框架源码专题:springIOC的加载过程,bean的生命周期,结合spring源码分析

    文章目录 1.BeanFactory和ApplicationContext的区别? 2. IOC与 Bean的加载过程 ①:初始化容器DefaultListableBeanFactory ②:创建读取 ...

  2. MediaPlayer的生命周期和缓冲策略 (源码篇)

    目录 概述 必备的知识体系 MediaPlayer的api MediaPlayer的setDataSource(path: String)流程 MediaPlayer::prepare的调用流程 Me ...

  3. Java并发基础:了解无锁CAS就从源码分析

    CAS的全称为Compare And Swap,直译就是比较交换.是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,在i ...

  4. Java并发基础:了解无锁CAS就从源码分析 1

    CAS的全称为Compare And Swap,直译就是比较交换.是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,在i ...

  5. C语言零基础项目:生命游戏!详细思路+源码分享

    每天一个C语言小项目,提升你的编程能力! 程序简介 生命游戏也叫康威生命游戏.细胞自动机.元胞自动机等. 生命游戏不需要任何玩家,它是一个二维矩形世界,这个世界中的每个方格居住着一个活细胞或为空. 一 ...

  6. iOS之深入解析WKWebView加载的生命周期与代理方法

    一.前言 从 WebView 开始加载一条请求,到页面完整呈现这一过程发生了什么?无论是做 WebView 性能优化还是异常问题监控与排查,都离不开对WKWebView加载的生命周期与代理方法的剖析. ...

  7. 深入java并发包源码(三)AQS独占方法源码分析

    深入java并发包源码(一)简介 深入java并发包源码(二)AQS的介绍与使用 深入java并发包源码(三)AQS独占方法源码分析 AQS 的实现原理 学完用 AQS 自定义一个锁以后,我们可以来看 ...

  8. Java多线程——线程的优先级和生命周期

    Java多线程--线程的优先级和生命周期 摘要:本文主要介绍了线程的优先级以及线程有哪些生命周期. 部分内容来自以下博客: https://www.cnblogs.com/sunddenly/p/41 ...

  9. 详解java中Thread类,线程和进程的基本区别,多线程的好处,线程的五个生命周期,主线程和IDEA创建的Monitor Ctrl-Break守护线程;优雅地终止线程。死锁的产生

    线程:CPU调度的最小单位:线程共享堆内存和方法区,但各自享有栈空间.进程:CPU分配资源的最小单位. 为什么需要多线程:①避免其中一个模块阻塞造成系统假死:②程序异步处理(交替执行),提高程序执行效 ...

最新文章

  1. 前百度主任架构师创业,两年融资千万美元,他说AI新药研发将迎来黄金十年...
  2. android自定义图片文本,Android 实现文字与图片的混排
  3. Java randomString
  4. vue3——ref reactive函数
  5. STM32程序的烧录方式 与 ISP一键下载
  6. 史上最通俗易懂的并查集算法详解
  7. Separating Pebbles数学,暴力
  8. Deecamp 面试翻车记录
  9. 【公司邮箱怎么注册】Foxmail帐户邮箱数据保存在什么地方?如何备份一个帐户?
  10. QQ,微信能聊天都靠它(socket)?
  11. python100day - day24 - DataAnalysis
  12. 程序员如何选择适合自己的企业?
  13. qt 计算字符串宽度高度
  14. C语言内存分布图----栈空间、堆空间
  15. Scrapy 豆瓣搜索页爬虫
  16. Direct3D显示视频
  17. 选定区域着色html,一种提取html页面选定区域内容的方法
  18. linux挂起 终端连不上吗,Linux系统11个不能不知道的终端命令
  19. HFirst解读和复现心得
  20. Debian10使用本地ISO搭建APT源

热门文章

  1. zabbix的日常监控-自动发现端口并监测(服务器开启的所有端口或监控指定端口)(十三)...
  2. vue-electron 写一个markdown文章编辑器(一)
  3. Java多线程超详细总结
  4. mysql 有两种数据库引擎发音
  5. NOIp #2011
  6. 机房收费系统学生下机结账小结
  7. 学习strut时遇到的问题 - Unable to compile class for JSP 错误的解决过程。
  8. 项目管理在企业发展中的作用及未来的发展方向—— 来自项目管理群的讨论
  9. 发生TM锁争用的情况
  10. Linux Shell常用技巧(四)