线程八大核心+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