【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,后者会继承父线程的本地变量 ...
随机推荐
- eclipse中 项目-->属性-->为什么没有deployment assembly 选项
原因: 因为当前的maven工程不是web工程,需要转换成web工程. 解决方法: 右击工程属性,找到Project Facets,选择Dynamic Web Module,2.5 点击apply.这 ...
- 微信小程序初始化 operateWXData:fail invalid scope
初学者开发微信小程序,可以使用云开发来进行微信小程序的开发. 第一次使用开发工具遇到的问题 解决方案:1.找到云开发 2.点击开通,选择合适自己的开发环境: 3.完成后,返回开发工具界面点击项目第一个 ...
- sharepoint 2013 service pack 和 Hotfix 版本
方法1:Central Administration > System Settings > Manage servers in your farm (/_admin/FarmServer ...
- bin/hdfs dfs命令
appendToFile Usage: hdfs dfs -appendToFile <localsrc> ... <dst> 追加一个或者多个文件到hdfs制定文件中.也可以 ...
- Keepalived + haproxy双机高可用方案
上一篇文章已经讲到了keepalived实现双机热备,且遗留了一个问题 master的网络不通的时候,可以立即切换到slave,但是如果只是master上的应用出现问题的时候,是不会 主动切换的. 上 ...
- 关于elasticsearch 6.x及其插件head安装(单机与集群)5分钟解决
第一步,下载es6 +head wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.zip wg ...
- python第十三课——嵌套循环
2.嵌套循环: 概念:循环中再定义循环,称为嵌套循环: [注意]嵌套循环可能有多层,但是一般我们实际开发最多两层就可以搞定了(99%的情况) 格式: 1).while中套while常用 2).whil ...
- 【2016蓝桥杯省赛】试题C++ B组试题
一. 煤球数目 作答:171700 #include <iostream> using namespace std; int main() { ,x=; ;i<=;i++){ ...
- 多线程之Timer和TimerTask
Timer是一种线程设施,用于安排以后在后台线程中执行的任务.可安排任务执行一次,或者定期重复执行,可以看成一个定时器,可以调度TimerTask.TimerTask是一个抽象类,实现了Runnabl ...
- centos下Zabbix Agent端部署和安装
首先重复一下前面的规划 server端: 192.168.136.144 centos6.5 (虚拟机) agent端: 192.168.136.155 centos6.5( 虚拟 ...