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可以 ...
随机推荐
- Linear regression with one variable - Cost function intuition I
摘要: 本文是吴恩达 (Andrew Ng)老师<机器学习>课程,第二章<单变量线性回归>中第8课时<代价函数的直观认识 - 1>的视频原文字幕.为本人在视频学习过 ...
- 【编程开发】 C与C++中的关于函数指针的强制类型转换与指针函数的关系
[编程开发] C与C++中的关于函数指针的强制类型转换与指针函数的关系 标签: [编程开发] [VS开发] 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 以 ...
- Linux Shell中的变量声明和一些特殊变量
在SHELL中定义变量比较直接,无类型区别,不需要像Java那样定义好是String还是int等. 声明变量需要遵守或者注意的几点: 变量名和等号之间不能有空格. 变量名首字符必须为字母. 变量名里可 ...
- 【转载】SpringBoot-配置发送邮件遇到的一些问题
前言:前一天调用163邮箱发送邮件还么有问题,今天再调用就各种发送不成功,害的我都关闭授权,还花了一毛钱短信费重新开启授权,最后百度到了一篇文章,非常贴切,在此转载下. 本人遇到的错误代码是554,邮 ...
- 网络流+最小生成树的最少割边数--How Many to Be Happy?
题意:https://blog.csdn.net/Ratina/article/details/95200594 思路: 首先我们知道最小生成树就是按长度枚举边,能连就连. 那么,如果这条边在最小生成 ...
- python+socket实现网络信息交互及文件传输
Socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. Socket又称"套接字",应用程序通常通过"套接字" ...
- shell习题第17题:检测磁盘
[题目要求] 写一个shell脚本,检测所有磁盘分区使用率和inode使用率并记录到以当天日期命名的日志文件里,当发现某个分区容量或者inode使用量大于85%时候,发邮件提醒 [核心要点] df d ...
- Python Socket套接字编程
Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...
- Asp.net core 学习笔记 ef core Surrogate Key, Natural Key, Alternate Keys
更新: 2019-12-23 foreignkey 并不一样要配上 alternate key,其实只要是 unique 就可以了. 和 sql server 是一样的, 经常有一种错觉 primar ...
- Spring、SpringMVC版本及配置
一.Spring版本 Spring的最新版本是Spring 5.x,Spring 4.x的最后版本是Spring 4.3.x,会维护到2020年(Spring的GitHub主页对此有说明). 二.Sp ...