【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,后者会继承父线程的本地变量 ...
随机推荐
- 北美Developer生存发展攻略
http://www.followmedoit.com/bbs/forum.php?mod=viewthread&tid=49&extra=page%3D1 在北美,做PM不易,而做D ...
- Linux crontab命令详解
crontab:定时任务的守护进程,精确到分,设计秒的我们一般写脚本 -->相当于闹钟 日志文件: ll /var/log/cron* 编辑文件: vim /et ...
- 申请Let’s Encrypt永久免费SSL证书过程教程及常见问题
配置证书https://easy.zhetao.com/ 虽然目前Let’s Encrypt免费SSL证书默认是90天有效期,但是我们也可以到期自动续约,不影响我们的尝试和使用,为了考虑到文章的真 ...
- Mac环境下WingIDE切换python版本
https://www.cnblogs.com/fastLearn/p/6514442.html
- Log4net 使用之 自定义字段
Log4net 是.Net下一个非常优秀的开源日志记录组件.Log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介. 由于业务需要,计划为日志增加2个字段,除了 ...
- [T-ARA][Apple is A]
歌词来源:http://music.163.com/#/song?id=22704474 달콤달콤해 짜릿짜릿해 [tal-Kom-dal-Ko-mae jja-lid-jja-li-Tae] 반짝반 ...
- JavaScript的DOM操作获取元素的大小
通过 style 内联获取元素的大小 需要注意的是style 获取只能获取到行内 style 属性的 CSS 样式中的宽和高,如果有获取:如果没有则返回空. <!DOCTYPE html> ...
- Java基础加强之并发(二)常用的多线程实现方式
概述 常用的多线程实现方式有2种: 1. 继承Thread类 2. 实现Runnable接口 之所以说是常用的,是因为通过还可以通过JUC(java.util.concurrent)包中的线程池来实现 ...
- msf提权基础(一)
令牌(token)相当于系统的临时密钥(账号及密码) 加载incognito模块 meterpreter> use incognito meterpreter > list_tokens ...
- python pip安装报错: ConnectTimeoutError
错误: 解决方案: 使用镜像:pip install xxxx -i https://pypi.douban.com/simple 如:pip3 install --upgrade tensorf ...