一、前言

不知道哪位古人说:人生三大境界。第一境界是:看山是山看水是水;第二境界是看山不是山看水不是水;第三境界:看山还是山看水还是水。

其实我想对于任何一门技术的学习都是这样。

形而上下者为之器,形而上者为之道。一直很喜欢自己大一的高数老师,老师是老教授了,他讲数学,会引申到建筑学,计算机科学,以及哲学再到生活中的常识。也能从其他学科、日常生活中,提取出数学的概念。我想,这就是形而上者了。

不胜望之

不多言,这里我们来深入java底层,看下java表皮之下的筋肉以及内脏。

二、从一段代码展开

package thread;

/**

* @author xuyuanpeng

* @version 1.0

* @date 2019-05-17 17:04

*/

public class ThreadMain {

public static void main(String[] args) {

Thread thread=new Thread(() -> {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

});

Thread t2=new Thread(() -> {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

});

log("线程1开始");

thread.start();

log("线程1结束");

log("线程2开始");

t2.run();

log("线程2结束");

}

public static void log(String msg){

System.err.print(System.currentTimeMillis());

System.out.println(">>>"+msg);

}

public static void log(){

log("");

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

这里可以思考下输出的结果:

1

2

3

铛铛铛档

Connected to the target VM, address: ‘127.0.0.1:51304’, transport: ‘socket’

1558085396255>>>线程1开始

1558085396255>>>线程1结束

1558085396255>>>线程2开始

1558085397255>>>线程2结束

Disconnected from the target VM, address: ‘127.0.0.1:51304’, transport: ‘socket’

细心的同学肯定已经发现了

线程1是start的方式启动,而线程2是run方法启动

差异在哪?

线程1执行start,并没有阻塞线程

而线程2的run方法,阻塞了线程。何改咯?┓( ´∀` )┏

为什么是这样的呢?start与run的区别究竟在哪呢?让我们深入她,张爱玲说,了解一个女人最好的通道就是XX,所以让我们深入她,再了解她。

三、JDK源码分析

1、start方法

public synchronized void start() {

/**

/**

* Causes this thread to begin execution; the Java Virtual Machine

* calls the run method of this thread.

*

* 1、start方法将导致当前线程开始执行。由JVM调用当前线程的run方法。

*

* The result is that two threads are running concurrently: the

* current thread (which returns from the call to the

* start method) and the other thread (which executes its

* run method).

*

* 2、结果是 调用start方法的当前线程 和 执行run方法的另一个线程 同时运行。

*

* It is never legal to start a thread more than once.

* In particular, a thread may not be restarted once it has completed

* execution.

*

* 3、多次启动线程永远不合法。 特别是,线程一旦完成执行就不会重新启动。

*

* @exception IllegalThreadStateException if the thread was already started.

* 如果线程已启动,则抛出异常。

* @see #run()

* @see #stop()

*/

public synchronized void start() {

/**

* This method is not invoked for the main method thread or "system"

* group threads created/set up by the VM. Any new functionality added

* to this method in the future may have to also be added to the VM.

*

* 4、对于由VM创建/设置的main方法线程或“system”组线程,不会调用此方法。

* 未来添加到此方法的任何新功能可能也必须添加到VM中。

*

* A zero status value corresponds to state "NEW".

* 5、status=0 代表是 status 是 "NEW"。

*/

if (threadStatus != 0)

throw new IllegalThreadStateException();

/* Notify the group that this thread is about to be started

* so that it can be added to the group's list of threads

* and the group's unstarted count can be decremented.

*

* 6、通知组该线程即将启动,以便将其添加到线程组的列表中,

* 并且减少线程组的未启动线程数递减。

*

* */

group.add(this);

boolean started = false;

try {

//7、调用native方法,底层开启异步线程,并调用run方法。

start0();

started = true;

} finally {

try {

if (!started) {

group.threadStartFailed(this);

}

} catch (Throwable ignore) {

/* do nothing. If start0 threw a Throwable then it will be passed up the call stack

* 8、忽略异常。 如果start0抛出一个Throwable,它将被传递给调用堆栈。

*/

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

start方法用synchronized修饰,为同步方法;

虽然为同步方法,但不能避免多次调用问题,用threadStatus来记录线程状态,如果线程被多次start会抛出异常;threadStatus的状态由JVM控制。

使用Runnable时,主线程无法捕获子线程中的异常状态。线程的异常,应在线程内部解决。

2、native start0方法

private native void start0();

1

native 是声明本地方法,在此处是JVM中的方法。

3、run方法

/**

* If this thread was constructed using a separate

* Runnable run object, then that

* Runnable object's run method is called;

* otherwise, this method does nothing and returns.

*

* Subclasses of Thread should override this method.

*

* @see #start()

* @see #stop()

* @see #Thread(ThreadGroup, Runnable, String)

*/

@Override

public void run() {

if (target != null) {

target.run();

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

run方法就很简单了,就是回调了Runable的run()接口

导致Thread写的@Overwrite void run() 方法直接是在主线程执行,导致阻塞了主线程。

四、总结

到此我们就知道了,start会使重写的run方法被虚拟机调用,是在子线程中执行的run方法

而直接调用线程的run方法,他是内部回调了run接口,导致直接执行了Runable.run的重写内容。相当于直接在主线程中执行。

---------------------

java看山不是山_java线程启动原理分析相关推荐

  1. java并发包线程池原理分析锁的深度化

    java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素 ...

  2. python内嵌函数和闭包与java 匿名内部类_Java匿名内部类构造原理分析

    很明显,我们的匿名内部类有了名字 InnerTest$1,而且是继承自 Test class InnerTest$1 extends Test 这个类中有一个成员final InnerTest thi ...

  3. java线程池饱和策略_干货:Java几种线程池的分析和使用。

    原标题:干货:Java几种线程池的分析和使用. 利用线程池的优势: 1.降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 2.提高响应速度.当任务到达时,任务可以不需要等到线程创建 ...

  4. Tomcat线程池监控及线程池原理分析

      目录         一.背景         二.tomcat线程池监控         三.tomcat线程池原理         四.总结 一.背景 我们都知道稳定性.高可用对于一个系统来讲 ...

  5. 4、Eureka 源码解析 之 Eureka Client 启动原理分析

    在前面的一篇文章 3.Eureka 源码解析 之 Eureka Server 启动原理分析当中我们分析了一下 Eureka Server 的启动.在集群环境下 Eureka Server 相互之前需要 ...

  6. Spring Boot(四):Spring Boot启动原理分析

    文章目录 Spring Boot启动原理分析 一.依赖导入原理 二.Spring Boot包扫描原理 三.Spring Boot自动配置原理 Spring Boot启动原理分析 一.依赖导入原理 父项 ...

  7. java 线程池原理分析

    一.为什么使用线程池 1.降低资源消耗,减少线程创建和销毁次数,每个工作线程可以重复利用,执行多个任务 2.可根据系统承受能力,调整工作线程的数目,防止消耗过多的内存 二.java 线程池使用 Exe ...

  8. java 线程池的理解_JAVA线程池原理的理解

    线程池原理基础理解: 线程池初始化规定个数的线程,然后这些线程一直运行,并且监控线程队列,只要线程队列被添加进线程,那么线程池不断从队列中取出线程运行.直到队列中的线程为空.实例代码如下: packa ...

  9. Java-Java中的线程池原理分析及使用

    文章目录 概述 线程池的优点 线程池的实现原理 线程池的使用 创建线程池 向线程池中提交任务 关闭线程池 合理的配置线程池 线程池的监控 概述 我们在上篇博文 Java-多线程框架Executor解读 ...

最新文章

  1. 03 Java程序员面试宝典视频课程之常用类
  2. 探寻背后的机制化繁为简:网站程序升级不过是文件同步
  3. 踩到一个Emit的坑,留个纪念
  4. 怎么样让自己更加从容的面对生活
  5. delphi7注册码
  6. Numpy练习题100题-提高你的数据分析技能
  7. linux命令crontab
  8. springboot整合elasticsearch_Spring Boot学习10_整合Elasticsearch
  9. python cpu_python 让cpu满载
  10. 疑似一加7 Pro 5G版通过3C认证:配备30W快充头
  11. Eclipse启动时报错Java was started but returned exit code=13
  12. 基于LSTM搭建文本情感分类的深度学习模型:准确率95%
  13. 顶尖的语音识别软件――Nuance Recognizer_语音识别_CTI论坛
  14. 大家社区荣获最具影响力品牌
  15. R与Python手牵手:数据科学导论系列(包的载入)
  16. struts2的package和result的标签的属性
  17. RNAcentral:非编码RNA数据库
  18. linux思源黑体乱码,deepin终端使用思源黑体做中文字体
  19. 8种经典的统计学悖论18种经典的哲学悖论
  20. 解密DB2独步江湖之五大法宝

热门文章

  1. 心灵鸡汤可以作为学习材料吗?-好的学习材料的重要性
  2. 干货!消息队列RabbitMQ入门教程
  3. subString与split区别
  4. centos服务器中木马后的处理和预防
  5. matlab 向量场线积分
  6. 大学生会用计算机的重要性,聊聊大学生电脑的一些事情
  7. 计算机应用基础名言名句大全,计算机应用基础实训指导书-上.doc
  8. vue blob流下载zip文件,下载后包文件显示文件损坏
  9. 加班少的真实原因是啥?
  10. handlebar 初学笔记