java线程基础巩固---线程生命周期以及start方法源码剖析
上篇中介绍了如何启动一个线程,通过调用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。
java线程基础巩固---线程生命周期以及start方法源码剖析的更多相关文章
- Java并发基础:了解无锁CAS就从源码分析
https://segmentfault.com/a/1190000015881923
- java多线程(2)---生命周期、线程通讯
java生命周期.线程通讯 一.生命周期 有关线程生命周期就要看下面这张图,围绕这张图讲解它的方法的含义,和不同方法间的区别. 1.yield()方法 yield()让当前正在运行的线程回到就绪 ...
- [转]Java 对象锁-synchronized()与线程的状态与生命周期
线程的状态与生命周期 Java 对象锁-synchronized() ? 1 2 3 4 synchronized(someObject){ //对象锁 } 对象锁的使用说明: 1.对象锁的返 ...
- Java多线程——线程的优先级和生命周期
Java多线程——线程的优先级和生命周期 摘要:本文主要介绍了线程的优先级以及线程有哪些生命周期. 部分内容来自以下博客: https://www.cnblogs.com/sunddenly/p/41 ...
- ☕【Java技术指南】「难点-核心-遗漏」Java线程状态流转及生命周期的技术指南(知识点串烧)!
前提介绍 本章主要介绍相关线程声明周期的转换机制以及声明周期的流转关系以及相关AQS的实现和相关的基本原理,配合这相关官方文档的中英文互译的介绍. 线程状态流转及生命周期 当线程被创建并启动以后,它既 ...
- Java Servlet系列之Servlet生命周期
Servlet生命周期定义了一个Servlet如何被加载.初始化,以及它怎样接收请求.响应请求,提供服务.在讨论Servlet生命周期之前,先让我们来看一下这几个方法: 1. init()方法 在Se ...
- Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程
下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...
- Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量
Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程: 1.线程是一堆指令,是操作系统调度 ...
- 014-多线程-基础-Exchanger-行线程间的数据交换
一.简介 Exchanger类允许在两个线程之间定义同步点,当两个线程都到达同步点时,它们交换数据.也就是第一个线程的数据进入到第二个线程中,第二线程的数据进入到第一个线程中. Exchanger可以 ...
随机推荐
- 剑指offer 67. 字符串转换为整数(Leetcode 8. String to Integer (atoi))
题目:剑指offer 67题 需要考虑的情况:空指针.nullptr.空字符串"".正负号.数值溢出.在写代码的时候对这些特殊的输入都定义好合理的输出.可以定义一个全局布尔型变量g ...
- YUV格式全解
YUV是指亮度参量和色度参量分开表示的像素格式,而这样分开的好处就是不但可以避免相互干扰,还可以降低色度的采样率而不会对图像质量影响太大.YUV是一个比较笼统地说法,针对它的具体排列方式,可以分为很多 ...
- Encoding.GetEncoding 编码列表
代码页 名称 显示名称 37 IBM037 IBM EBCDIC(美国 - 加拿大) 437 IBM437 OEM 美国 500 IBM500 IBM EBCDIC(国际) 708 A ...
- [百度贴吧]飞腾1500a .VS. 龙芯3a3000: 同频实用性能对比
贴吧关于 龙芯与飞腾的简单对比. https://tieba.baidu.com/p/5682824804?red_tag=0221728732 龙芯3a3000实用性能 ,还不如4年前发布的FT15 ...
- 落网数据库简单查询接口 caddy+php7+mongodb
落网数据库简单查询接口 一个简单的DEMO,使用了caddy + php7 + mongodb 数据库&接口设计 来自 https://github.com/Aedron/Luoo.spide ...
- 基于DNS(Consul)高可用
DNS 推荐从Bind-DLZ入手,资料多可控制度更好(查询DNS记录SQL可定制)据说性能差 Bind-DLZhttps://www.cnblogs.com/saneri/p/8178065.htm ...
- shell使用ps -ef|grep xxx时不显示grep xxx进程的方法
在使用ps -ef|grep xxx时会将grep xxx的进程也带出来, 而在脚本中如果想要截取此命令结果的一部分,则grep xxx的进程会显得多余,如下: [root@localhost ~]# ...
- kafka常见问题
(1) 如果想消费已经被消费过的数据 consumer是底层采用的是一个阻塞队列,只要一有producer生产数据,那consumer就会将数据消费.当然这里会产生一个很严重的问题,如果你重启一消费 ...
- MyBatis 源码篇-DataSource
本章介绍 MyBatis 提供的数据源模块,为后面与 Spring 集成做铺垫,从以下三点出发: 描述 MyBatis 数据源模块的类图结构: MyBatis 是如何集成第三方数据源组件的: Pool ...
- 怎样禁用浏览器的Cookie功能
使用: window.navigator.cookieEnabled; window.navigator.cookieEnabled = true; 这样设置以后, 浏览器就不会接受和保存服务器传过来 ...