【Java源码解析】Thread
简介
线程本质上也是进程。线程机制提供了在同一程序内共享内存地址空间运行的一组线程。对于内核来讲,它就是进程,只是该进程和其他一下进程共享某些资源,比如地址空间。在Java语言里,Thread类封装了线程相关的特性,使用其进行多线程编程。
源码解析
线程状态
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
认识3个队列
- threadScheduleQueue,线程调度队列,操作系统根据此队列给每个线程分配CPU时间片
- synchronousQueue,同步队列,多个线程争用同一把锁时,未抢到锁的线程会在此队列里等待
- conditionQueue,条件队列,抢到锁的线程要等待某个条件而释放锁就会进入此队列里被别的拿到锁的线程唤醒。
三个队列的关系
一个线程自创建起,一定是先被安排进入threadScheduleQueue,轮到它的时间片投入运行,遇见临界区,抢锁失败后会进入synchronousQueue,可能 要等待某个条件,继而进入conditionQueue,
如果别的线程唤醒它,离开conditionQueue,进入synchronousQueue,继续抢占锁,执行完同步代码块,最后回到threadScheduleQueue,等待下次被调度。
线程状态
- NEW,线程刚刚创建,尚未启动
- RUNNABLE,可运行,此时线程在threadScheduleQueue
- BLOCKED,阻塞(在某把锁上),此时线程在synchronousQueue
- WAITING,等待某个条件,此时线程在conditionQueue
- TIMED_WAITING,带超时的WAITING
- TERMINATED,线程终止
线程状态转换

属性
private volatile char name[]; // 线程名称
private int priority; // 优先级
private Thread threadQ;
private long eetop;
private boolean single_step; // 是否单步执行
private boolean daemon = false; // 是否是守护线程
private boolean stillborn = false;
private Runnable target; // 目标任务
private ThreadGroup group; // 线程组
private ClassLoader contextClassLoader; // 上下文类加载器
private AccessControlContext inheritedAccessControlContext; // 继承的访问控制上下文
private static int threadInitNumber; // 线程编号 private static synchronized int nextThreadNum() {
return threadInitNumber++;
} ThreadLocal.ThreadLocalMap threadLocals = null; // 线程本地变量Map
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; // 线程本地变量Map,会继承父线程的变量初始值
private long stackSize; // 该线程请求的堆栈大小
private long nativeParkEventPointer;
private long tid; // 线程ID
private static long threadSeqNumber; // 用来生成线程ID
private volatile int threadStatus = 0; // 线程状态 private static synchronized long nextThreadID() {
return ++threadSeqNumber;
} volatile Object parkBlocker; // 中断阻塞器
private volatile Interruptible blocker;
private final Object blockerLock = new Object(); // 阻塞锁 void blockedOn(Interruptible b) {
synchronized (blockerLock) {
blocker = b;
}
} public final static int MIN_PRIORITY = 1; // 线程最小优先级
public final static int NORM_PRIORITY = 5; // 默认优先级
public final static int MAX_PRIORITY = 10; // 最大优先级
构造方法
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(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
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) {
init(group, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}
都会调用init方法。
init()
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) {
if (security != null) {
g = security.getThreadGroup();
}
if (g == null) {
g = parent.getThreadGroup();
}
}
g.checkAccess(); // 检查访问权限
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted(); // 添加线程到组
this.group = g; // 设置线程组
this.daemon = parent.isDaemon(); // 继承父线程的daemon属性
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);
this.stackSize = stackSize;
tid = nextThreadID(); // 设置线程ID
}
start()
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();
interrupt()
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // 设置中断标记
b.interrupt(this);
return;
}
}
interrupt0();
}
private native void interrupt0();
join()
public final synchronized void join(long millis) throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0); // 调用object的wait()方法
}
} else {
while (isAlive()) { // 带超时的join
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay); // 调用object的wait()方法
now = System.currentTimeMillis() - base;
}
}
}
行文至此结束。
尊重他人的劳动,转载请注明出处:http://www.cnblogs.com/aniao/p/aniao_thread.html
【Java源码解析】Thread的更多相关文章
- Java源码解析——集合框架(三)——Vector
Vector源码解析 首先说一下Vector和ArrayList的区别: (1) Vector的所有方法都是有synchronized关键字的,即每一个方法都是同步的,所以在使用起来效率会非常低,但是 ...
- Java源码解析——集合框架(二)——ArrayBlockingQueue
ArrayBlockingQueue源码解析 ArrayBlockingQueue是一个阻塞式的队列,继承自AbstractBlockingQueue,间接的实现了Queue接口和Collection ...
- [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析
String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识, ...
- [java源码解析]对HashMap源码的分析(二)
上文我们讲了HashMap那骚骚的逻辑结构,这一篇我们来吹吹它的实现思想,也就是算法层面.有兴趣看下或者回顾上一篇HashMap逻辑层面的,可以看下HashMap源码解析(一).使用了哈希表得“拉链法 ...
- java源码解析之Object类
一.Object类概述 Object类是java中类层次的根,是所有类的基类.在编译时会自动导入.Object中的方法如下: 二.方法详解 Object的方法可以分成两类,一类是被关键字fin ...
- Java源码解析——Java IO包
一.基础知识: 1. Java IO一般包含两个部分:1)java.io包中阻塞型IO:2)java.nio包中的非阻塞型IO,通常称为New IO.这里只考虑到java.io包中堵塞型IO: 2. ...
- java源码解析
String深入解析 String具有不变性的原因: String被final修饰,它不可能被继承,也就是任何对String的操作方法,都不会被继承覆写 String中保存数据的是一个char数组的v ...
- java源码解析——Stack类
在java中,Stack类继承了Vector类.Vector类和我们经常使用的ArrayList是类似的,底层也是使用了数组来实现,只不过Vector是线程安全的.因此可以知道Stack也是线程安全的 ...
- 【Java源码解析】ThreadLocal
简介 线程本地变量,用于同一线程之间的传递.每一个线程对象都保存在两个ThreadLocalMap,threadLocals和inheritableThreadLocals,后者会继承父线程的本地变量 ...
随机推荐
- Linux 系统的主机别名文件
修改主机名文件 # 方式一: 临时生效 hostname 主机名 hostname omc 临时生效 # 方式二: 编辑配置文件[永久生效] vim /etc/sysconfig/network [更 ...
- php5 Array 数组函数
函数 描述 array() 创建数组. array_change_key_case() 把数组中所有键更改为小写或大写. array_chunk() 把一个数组分割为新的数组块. array_colu ...
- C++ 读书笔记2
dfadsfa body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding ...
- Xpath注入学习
xpath简介: 提到xpath就要先说下xml,xml意为可扩展标记语言,简单来说就是一种存储数据的标准格式,可以把他视为一个小型的数据库,他可以解决数据在网上传输的标准问题.是一种比数据库更具通用 ...
- php函数substr_replace中文乱码的替代解决方法
$str = "中华人民共和国"; $len = mb_strlen($str,'utf-8'); if($len>=6){ $str1 = mb_substr($str,0 ...
- tomcat-7.0.30安装及配置
使用说明: 一.1.下载jdk(http://java.sun.com/javase/downloads/index.jsp),2.安装jdk-6u14-windows-i586.exe 3.配置环境 ...
- 个人作业2:APP案例分析--腾讯动漫
第一部分 调研,评测 个人第一次上手体验 以往看漫画就是在浏览器直接搜索在网页上看,直到用了腾讯动漫APP,我才摒弃这个很low的方法.腾讯动漫直接用qq就可以登陆,有更齐全的漫画分类,更清晰的画质, ...
- SGU---103 最短路变形
题目链接: https://cn.vjudge.net/problem/SGU-103#author=ECUST_FZL 题目大意: Dingiville 城市的交通规则非常奇怪,城市公路通过路口相连 ...
- BM求递推式模板
时间复杂度\(O(N^2)\),原理不明...... #include <cstdio> #include <cstring> #include <cmath> # ...
- Hive学习之路 (十七)Hive分析窗口函数(五) GROUPING SETS、GROUPING__ID、CUBE和ROLLUP
概述 GROUPING SETS,GROUPING__ID,CUBE,ROLLUP 这几个分析函数通常用于OLAP中,不能累加,而且需要根据不同维度上钻和下钻的指标统计,比如,分小时.天.月的UV数. ...