一文看尽Java-Thread
一、前言
主要分成两部说起:Thread源码解读和常见面试题解答,废话不多说开始;
二、源码解读
首先看下构造函数,构造函数都是通过调用init方法对属性进行初始化,主要是对线程组、线程名字、栈大小等信息进行初始化;init内部通过调用currentThread本地方法,获取当前的线程,这个本地方法封装在JVM中,有兴趣的可以看下这个这个链接查找下JVM实现https://hg.openjdk.java.net/jdk8u,接下来对ThreadGroup的判断,如果没有传入线程组的话, 第一是使用SecurityManager中的ThreadGroup, 如果从SecurityManager 中获取不到ThreadGroup(), 那么就从当前线程中获取线程组,最后做了检验和些参数的赋值,整体上相对比较简单;
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name.toCharArray();
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
/* Determine if it's an applet or not */
/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* If the security doesn't have a strong opinion of the matter
use the parent thread group. */
if (g == null) {
g = parent.getThreadGroup();
}
}
/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess();
/*
* Do we have the required permissions?
*/
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
tid = nextThreadID();
}
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
} public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc);
}
// 线程名
public Thread(String name) {
init(null, null, name, 0);
}
//线程组和线程名
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
//线程任务,线程名
public Thread(Runnable target, String name){
init(null, target, name, 0);
}
// 线程组, 线程任务, 线程名 ,栈大小
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}
接下来看下主要的属性:
// 类加载的时候,调用本地的注册本地方静态方法, 这个方法是本地方法
private static native void registerNatives();
static {
registerNatives();
}
private volatile char name[];
private int priority;
private Thread threadQ;
private long eetop;
/* Whether or not to single_step this thread. */
private boolean single_step;
/* Whether or not the thread is a daemon thread. */
// 设设置这个线程是否是守护线程
private boolean daemon = false;
/* JVM state */
private boolean stillborn = false;
/* What will be run. */
// 要执行的run方法的对象
private Runnable target;
/* The group of this thread */
// 这个线程的线程组
private ThreadGroup group;
/* The context ClassLoader for this thread */
// 这个线程的上下文类加载器
private ClassLoader contextClassLoader;
/* The inherited AccessControlContext of this thread */
private AccessControlContext inheritedAccessControlContext;
/* For autonumbering anonymous threads. */
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/*
* The requested stack size for this thread, or 0 if the creator did
* not specify a stack size. It is up to the VM to do whatever it
* likes with this number; some VMs will ignore it.
*/
// 给这个线程设置的栈的大小,默认为0
private long stackSize;
/*
* JVM-private state that persists after native thread termination.
*/
private long nativeParkEventPointer;
/*
* Thread ID
*/ //线程id
private long tid;
/* For generating thread ID */
private static long threadSeqNumber;
/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
private volatile int threadStatus = 0;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
/**
* The argument supplied to the current call to
* java.util.concurrent.locks.LockSupport.park.
* Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
* Accessed using java.util.concurrent.locks.LockSupport.getBlocker
*/
volatile Object parkBlocker;
/* The object in which this thread is blocked in an interruptible I/O
* operation, if any. The blocker's interrupt method should be invoked
* after setting this thread's interrupt status.
*/
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
/* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
*/
void blockedOn(Interruptible b) {
synchronized (blockerLock) {
blocker = b;
}
}
/**
* The minimum priority that a thread can have.
*/
// 线程执行的最低优先级 为1
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
// 线程默认的执行优先级为 5
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
// 线程执行的最高的优先级为 10
public final static int MAX_PRIORITY = 10;
最后介绍下方法的作用和线程状态,源码都比较简单,没必进行过多的介绍,都是通过调用JVM的本地方法实现;

线程状态:

三、常见面试题
1.线程与进程的区别?
进程是资源分配最小的单位,线程是CPU调度最小的单位;
线程属于进程,共享进程分配的资源;
进程属于抢占式调度,资源不相互共享;
2.start和run的区别?
run是Thread的一个普通的方法;
start方法会创建一个新的子线程并启动;
3.sleep与wait的区别?
sleep是Thread方法,wait是Object的方法;
wait方法只能在synchroized方法或者块中使用;
Thread.sleep只会让出CPU,不会改变锁的行为;
Object.wait不仅会让出CPU,同时还会释放占有同步资源的锁;
4.线程状态的转化?
图中将WAITING 和TIMED_WAITING 两个状态合并为WAITING ,没有分开,大家不要搞错;

5.如何处理线程的返回值?
主线程等待法,使用while等待主线程返回值;
join阻塞当前线程以等待子线程;
通过FuTureTask获取子线程的返回值;
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
String value="test";
System.out.println("start");
Thread.sleep(5000);
System.out.println("end");
return value;
}
}
public class FutureTaskDemo {
public static void main(String[] main) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask=new FutureTask<String>(new MyCallable());
new Thread(futureTask).start();
if (!futureTask.isDone()){
System.out.println("waiting");
}
System.out.println("return"+futureTask.get());
}
}
通过线程池获取返回值;
public class ThreadPoolDemo {
public static void main(String[] args){
ExecutorService executorService= Executors.newCachedThreadPool();
Future<String> futureTask=executorService.submit(new MyCallable());
if (!futureTask.isDone()){
System.out.println("wait");
}
try {
System.out.println(futureTask.get());
}catch (InterruptedException ex){
ex.printStackTrace();
}catch (ExecutionException ex){
ex.printStackTrace();
}finally {
executorService.shutdown();
}
}
}
6.Thread和Runnable?
Thread是类,Runnable是接口,Thread是Runnable实现;
类的继承单一原则,Runnable是更高层次的抽象;
四、结束
欢迎大家加群438836709!欢迎大家关注我!

一文看尽Java-Thread的更多相关文章
- 一文看懂Java序列化
一文看懂Java序列化 简介 Java实现 Serializable 最基本情况 类的成员为引用 同一对象多次序列化 子父类引用序列化 可自定义的可序列化 Externalizable:强制自定义序列 ...
- 一文看懂java io系统 (转)
出处: 一文看懂java io系统 学习java IO系统,重点是学会IO模型,了解了各种IO模型之后就可以更好的理解java IO Java IO 是一套Java用来读写数据(输入和输出)的A ...
- 一文看懂Java Worker 设计模式
Worker模式 想解决的问题 异步执行一些任务,有返回或无返回结果 使用动机 有些时候想执行一些异步任务,如异步网络通信.daemon任务,但又不想去管理这任务的生命周.这个时候可以使用Worker ...
- 一文看懂Java序列化之serialVersionUID
serialVersionUID适用于Java的序列化机制.简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的 ...
- 一文看懂java的IO流
废话不多说,直接上代码 import com.fasterxml.jackson.databind.ObjectMapper; import java.io.*; import java.nio.ch ...
- Java Thread.interrupt interrupted
Java Thread.interrupt @(Base)[JDK, 线程, interrupt] 原文地址,转载请注明 下面这个场景你可能很熟悉,我们调用Thread.sleep(),conditi ...
- 一文读懂JAVA多线程
背景渊源 摩尔定律 提到多线程好多书上都会提到摩尔定律,它是由英特尔创始人之一Gordon Moore提出来的.其内容为:当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍 ...
- Java Thread 的 sleep() 和 wait() 的区别
Java Thread 的使用 Java Thread 的 run() 与 start() 的区别 Java Thread 的 sleep() 和 wait() 的区别 1. sleep ...
- Java Thread wait, notify and notifyAll Example
Java Thread wait, notify and notifyAll Example Java线程中的使用的wait,notify和nitifyAll方法示例. The Object clas ...
- 性能分析之-- JAVA Thread Dump 分析综述
性能分析之-- JAVA Thread Dump 分析综述 一.Thread Dump介绍 1.1什么是Thread Dump? Thread Dump是非常有用的诊断Java应用问题的工 ...
随机推荐
- IO流1
一.I/0:input/output1.java.io.file表示:文件或文件夹(目录)File f = new File("文件路径");注意:相对路径:非web项目的相对都是 ...
- Linux再学习(一)-学习路线规划
1 抛弃旧文化,迎接Linux命令新文化 Linux第一步,从Windows思维,切换到Linux的"命令行+文件"模式 在Linux中,做什么都有相应命令.一般就在bin或者sb ...
- Linux基础进程管理
一.进程 了解如进程的: • PID,PPID • 当前的进程状态 • 内存的分配情况 • CPU和已花费的实际时间 • 用户UID,他决定进程的特权 (一).静态查看进程 # ps axu | le ...
- Alfred Workflow
实用的 Alfred Workflow Alfred Workflow 介绍 alfred-pkgman-workflow 快速从各个软件仓库(maven, gradle 等等)中查找需要的软件包 A ...
- alluxio源码解析-层次化存储(4)
层次化存储-特性介绍: https://www.alluxio.org/docs/1.6/cn/Tiered-Storage-on-Alluxio.html 引入分层存储后,Alluxio管理的数据块 ...
- maven3实战之仓库
maven3实战之仓库(maven仓库分类) maven3实战之仓库(maven仓库分类) ---------- 对于maven来说,仓库只分为两类:本地仓库和远程仓库.当maven根据坐标寻找构件的 ...
- 分布式ID系列(5)——Twitter的雪法算法Snowflake适合做分布式ID吗
介绍Snowflake算法 SnowFlake算法是国际大公司Twitter的采用的一种生成分布式自增id的策略,这个算法产生的分布式id是足够我们我们中小公司在日常里面的使用了.我也是比较推荐这一种 ...
- cs231n---强化学习
介绍了基于价值函数和基于策略梯度的两种强化学习框架,并介绍了四种强化学习算法:Q-learning,DQN,REINFORCE,Actot-Critic 1 强化学习问题建模 上图中,智能体agent ...
- [GO语言的并发之道] Goroutine调度原理&Channel详解
并发(并行),一直以来都是一个编程语言里的核心主题之一,也是被开发者关注最多的话题:Go语言作为一个出道以来就自带 『高并发』光环的富二代编程语言,它的并发(并行)编程肯定是值得开发者去探究的,而Go ...
- 构建企业级数据湖?Azure Data Lake Storage Gen2不容错过(上)
背景 相较传统的重量级OLAP数据仓库,“数据湖”以其数据体量大.综合成本低.支持非结构化数据.查询灵活多变等特点,受到越来越多企业的青睐,逐渐成为了现代数据平台的核心和架构范式. 数据湖的核心功能, ...