线程八大核心+Java并发底层原理精讲 Java并发核心知识体系精讲 第四章 学习笔记

线程八大核心+Java并发底层原理精讲 Java并发核心知识体系精讲 第四章 学习笔记

最后附上下载链接

线程八大核心+Java并发底层原理精讲 Java并发核心知识体系精讲 学习笔记

下载地址:

百度网盘:

链接: https://pan.baidu.com/s/1WBBj3CeCEi0arO_eFHsNSQ  密码: g8q0

第4章 核心2:开启多线程启动的世界

本章借着案例深入剖析start()和run()方法原理,最后以面试问题检验小伙伴学习成果,巩固本章知识。

4-1 启动线程的正确姿势

package threadcoreknowledge.startthread;
import threadcoreknowledge.createthreads.ThreadStyle;
/**
* 描述:对比start和run两种启动线程的方式
* @author wanghui
*/
public class StartAndRunMethod {

public static void main(String[] args) {
Runnable runnable = () -> {
System.out.println(Thread.currentThread().getName());
};
runnable.run();
new Thread(runnable).start();//正确的方法
}
}


4-2 start()方法原理解读

启动新线程:调用start()方法启动
准备工作
不能重复start

package threadcoreknowledge.startthread;

/**
* 描述:演示不能两次调用start方法,否则会报错
* @author wanghui
*/
public class CantStartTwice {
public static void main(String[] args) {
Thread thread = new Thread();
thread.start();
thread.start();
}
}

Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:708)
at threadcoreknowledge.startthread.CantStartTwice.main(CantStartTwice.java:11)

Process finished with exit code 1

启动新线程检查线程状态
加入线程组
调用start0()方法

private volatile int threadStatus = 0;
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
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 */
}
}
}

private native void start0();

native的start0是C++实现的

4-3 run()方法原理解读

/* What will be run. */
private Runnable target;

@Override
public void run() {
if (target != null) {
target.run();
}
}

 


4-4 彩蛋:【Java名字由来的奇闻轶事】


我们所见到的Java标志,总是一杯热咖啡,这杯热咖啡你很难与计算机编程联想到一起。这杯热咖啡、Java这个名字的由来,是Java创始人员团队中其中一名成员由于灵感想到的,想起自己在Java岛(爪哇岛)上曾喝过一种美味的咖啡,于是这种计算机编程语言就命名为Java,与此同时它的标起来是我们最熟悉不过的一杯热咖啡

4-5 线程常见面试问题

面试题1:一个线程两次调用start()方法会出现什么情况?为什么?

 让我们来看start()的源码

private volatile int threadStatus = 0;
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {group.threadStartFailed(this);}
} catch (Throwable ignore) {}
}
}
private native void start0();

 

 流程
1. 检查线程状态,只有NEW状态下的线程才能继续,否则会抛出 IllegalThreadStateException(在运行中或者已结束的线程,都不能再次启动,详见CantStartTwice10类)
2. 被加入线程组
3. 调用start0()方法启动线程

注意点:
1、start方法是被synchronized修饰的方法,可以保证线程安全。
2、由JVM创建的main方法线程和system组线程,并不会通过start来启动。

 解答
从源码可以看出,start的时候会先检查线程状态,只有NEW状态下的线程才能继续,否 则会抛出 IllegalThreadStateException。

面试题二: 既然Thread.start()只能调用一次。那么线程池是如何实现线程复用的呢?

线程重用的核心是,线程Thread做了包装,不重复调thread.start(),而是自己有一个Runnable.run(),run方法里面循环在跑,跑的过程中不断检查我们是否有新加入的子 Runnable对象, 有新的Runnable进来的话就调一下我们的run(),其实就一个大run()把其它小 run()#1,run()#2,...给串联 起来了。同一Thread可以执行不同的Runnable,主要原因是线程池把线程和Runnable 通过 BlockingQueue给解耦了,线程可以从BlockingQueue中不断获取新的任务。

面试题三:既然start()方法会调用run()方法,为什么我们选择调用start()方法,而不是直接调用run()方法呢?

start()才是真正启动一个线程,而如果直接调用run(),那么run只是一个普通的方法而已,和线程的生命周期没有任何关系。

 

线程八大核心+Java并发底层原理精讲 Java并发核心知识体系精讲 学习笔记

下载地址:

百度网盘:

链接: https://pan.baidu.com/s/1WBBj3CeCEi0arO_eFHsNSQ  密码: g8q0

如果失效:联系微信:itit11223344

 

线程八大核心+Java并发底层原理精讲 Java并发核心知识体系精讲 第四章 学习笔记_第1张图片

 

你可能感兴趣的:(线程八大核心+Java并发底层原理精讲 Java并发核心知识体系精讲 第四章 学习笔记)