盘一盘 Thread源码
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
继承关系图
线程的创建方式有很多种。常用的有:继承Thread(),重写该类的run()方法;实现Runnable接口,并重写该接口的run()方法。
其实Thread类本身也是实现了Runnable接口,而run()方法最先是在Runnable接口中定义的方法。
主要属性
- // 线程的名称
- private volatile char name[];
- // 线程的优先级
- private int priority;
- // 是否是单步执行
- private boolean single_step;
- // 是否是守护线程
- private boolean daemon = false;
- // JVM虚拟机的状态
- private boolean stillborn = false;
- // 将会被执行的 Runnable
- private Runnable target;
- // 当前线程的组
- private ThreadGroup group;
- // 当前线程的上下文
- private ClassLoader contextClassLoader;
- // 当前线程继承的访问控制权限
- private AccessControlContext inheritedAccessControlContext;
- // 默认线程的自动编号
- private static int threadInitNumber;
- // 得到下个thread ID
- private static synchronized int nextThreadNum() {
- return threadInitNumber++;
- }
- // 与当前线程有关的ThreadLocal值
- ThreadLocal.ThreadLocalMap threadLocals = null;
- // 与当前线程相关的InheritableThreadLocal值。
- ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
- // 该线程请求的堆栈大小 默认一般为空 JVM自行分配
- private long stackSize;
- // 当前线程终止后,JVM的私有状态
- private long nativeParkEventPointer;
- // 当前线程的专属ID
- private long tid;
- // 用来生成 thread ID
- private static long threadSeqNumber;
- // 线程状态,0代表线程未启动 Runable
- private volatile int threadStatus = 0;
- // 中断阻塞器:当线程发生IO中断时,需要在线程被设置为中断状态后调用该对象的interrupt方法
- 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;
构造方法
- // init方法相关参数
- // g 线程组
- // target 实现 Runnable接口类对象,就是调用 run方法的目标对象
- // name 线程名称
- // stackSize 栈的大小 该值对JVM而言只是一个建议,JVM会动态选择更合适的值
- // acc 访问控制权限
- 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();
- // 获取系统的security
- SecurityManager security = System.getSecurityManager();
- // 没有指定线程组的话,创建的所有线程属于相同的线程组。
- if (g == null) {
- // 先将secuity的线程组赋给新线程的线程组
- 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();
- 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;
- // 分配线程Id ThreadID是由JVM分配的,并不是系统的真正线程ID
- tid = nextThreadID();
- }
- private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
- init(g, target, name, stackSize, null);
- }
- 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);
- }
native方法
- // 获得当前线程
- public static native Thread currentThread();
- // 使当前线程从 运行状态Running 变为 就绪状态 Runnable
- public static native void yield();
- // 使当前线程进入休眠状态
- public static native void sleep(long millis) throws InterruptedException;
- // 使线程进入就绪状态 Runnable
- private native void start0();
- // 判断线程是否为中断状态
- private native boolean isInterrupted(boolean ClearInterrupted);
- // 判断线程是否存活
- public final native boolean isAlive();
- // 获取所有线程列表
- private native static StackTraceElement[][] dumpThreads(Thread[] threads);
- private native static Thread[] getThreads();
- // 设置线程优先等级
- private native void setPriority0(int newPriority);
- // 停止线程 该方法已被弃用
- private native void stop0(Object o);
- // 线程暂停
- private native void suspend0();
- // 线程继续执行
- private native void resume0();
- // 线程中断
- private native void interrupt0();
- // 设置线程名
- private native void setNativeName(String name);
这里不得不说和线程相关的几个Object Native方法。
- // 随机唤醒在此对象监视器(锁)上等待的单个线程。
- public final native void notify();
- // 唤醒所有等待在该对象上的线程。
- public final native void notifyAll();
- // 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法
- public final void wait() throws InterruptedException {
- wait(0);
- }
- // 超时等待一段时间,这里的参数是毫秒,也就是等待长达n毫秒,如果没有通知就超时返回。
- public final native void wait(long timeout) throws InterruptedException;
关键方法
start() 启动线程
- public synchronized void start() {
- // 判断线程状态是否启动,不允许同一线程启动2次!
- if (threadStatus != 0)
- throw new IllegalThreadStateException();
- // 向线程组中添加当前线程
- group.add(this);
- // 使线程进入就绪状态 Runnable
- 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 */
- }
- }
- }
checkAccess() 检查当前线程是否有修改权限,该方法在线程状态变更前多次被调用
- public final void checkAccess() {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- // 通过Java安全管理器检查当前线程是否有修改权限
- security.checkAccess(this);
- }
- }
run() 使线程从就绪状态 Runnable转化为运行状态 Running -todo线程启动过程中由start到run的过程非常复杂。
- public void run() {
- // 调用 run方法的目标对象
- if (target != null) {
- target.run();
- }
- }
exit() 该方法 run方法执行完成后调用,在线程结束退出之前进行清理工作。
- private void exit() {
- // 释放资源
- if (group != null) {
- group.threadTerminated(this);
- group = null;
- }
- target = null;
- threadLocals = null;
- inheritableThreadLocals = null;
- inheritedAccessControlContext = null;
- blocker = null;
- uncaughtExceptionHandler = null;
- }
- @Deprecated
- public final void stop() {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- checkAccess();
- if (this != Thread.currentThread()) {
- security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
- }
- }
- if (threadStatus != 0) {
- resume(); // Wake up thread if it was suspended; no-op otherwise
- }
- stop0(new ThreadDeath());
- }
interrupt() 中断线程
- public void interrupt() {
- if (this != Thread.currentThread())
- checkAccess();
- synchronized (blockerLock) {
- Interruptible b = blocker;
- if (b != null) {
- interrupt0(); // Just to set the interrupt flag
- b.interrupt(this);
- return;
- }
- }
- interrupt0();
- }
- public final void setPriority(int newPriority) {
- ThreadGroup g;
- checkAccess();
- // 线程优先级范围仅分 1~10 级
- if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
- throw new IllegalArgumentException();
- }
- if((g = getThreadGroup()) != null) {
- if (newPriority > g.getMaxPriority()) {
- newPriority = g.getMaxPriority();
- }
- setPriority0(priority = newPriority);
- }
- }
- public final int getPriority() {
- return priority;
- }
- public final void join() throws InterruptedException {
- join(0);
- }
- 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);
- }
- } else {
- while (isAlive()) {
- long delay = millis - now;
- if (delay <= 0) {
- break;
- }
- wait(delay);
- now = System.currentTimeMillis() - base;
- }
- }
- }
setDaemon() 将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
- public final void setDaemon(boolean on) {
- checkAccess();
- // 该方法必须在启动线程前调用
- if (isAlive()) {
- throw new IllegalThreadStateException();
- }
- daemon = on;
- }
盘一盘 Thread源码的更多相关文章
- 从Thread.start()方法看Thread源码,多次start一个线程会怎么样
这篇文章作为Thread类源码剖析的补充,从一个侧面来看Thread源码.也解答了面试高频问题:"多次start一个线程会怎么样?" 答案是:java.lang.IllegalTh ...
- java 并发编程——Thread 源码重新学习
Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...
- Handler、Looper、MessageQueue、Thread源码分析
关于这几个之间的关系以及源码分析的文章应该挺多的了,不过既然学习了,还是觉得整理下,印象更深刻点,嗯,如果有错误的地方欢迎反馈. 转载请注明出处:http://www.cnblogs.com/John ...
- Thread源码分析
本文为转载,请珍惜别人的劳动成果,注明转载地址:http://www.cnblogs.com/gw811/archive/2012/10/15/2724602.html 1.Runnable接口源码: ...
- Thread源码剖析
前言 昨天已经写了: 多线程三分钟就可以入个门了! 如果没看的同学建议先去阅读一遍哦~ 在写文章之前通读了一遍<Java 核心技术 卷一>的并发章节和<Java并发编程实战>前 ...
- Thread源码分析-java8
1.Thread特性分析 守护线程Daemon 定性:支持性线程,主要用于程序中后台调度以及支持性工作. 当JVM中不存在Daemon线程时,JVM将会退出. 将一个线程设定为Daemon的方法: 调 ...
- Java中Thread源码剖析
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 关于线程,用很长时间了,主线程下的子线程去做一些事情,就是一个代理模式,主线程分代理权给子线程,子线 ...
- 并发编程学习笔记(七、Thread源码分析)
目录: 常见属性 构造函数 start() run() 常见属性: /** * 线程名称 */ private volatile String name; /** * 线程优先级 */ private ...
- java Thread源码分析(二)
一.sleep的使用 public class ThreadTest { public static void main(String[] args) throws InterruptedExcept ...
随机推荐
- matlab 单元最短路 Dijkstra算法 无向图
W = [2 8 1 1 6 5 1 2 3 6 4 9 3 7 9]; S = [0 0 0 1 1 3 3 3 5 5 6 4 6 2 2];S=S+1; T = [1 3 2 4 3 4 5 6 ...
- 洛谷 P3768 简单的数学题 (莫比乌斯反演)
题意:求$(\sum_{i=1}^{n}\sum_{j=1}^{n}ijgcd(i,j))mod p$(p为质数,n<=1e10) 很显然,推式子. $\sum_{i=1}^{n}\sum_{j ...
- SELinux 宽容模式(permissive) 强制模式(enforcing) 关闭(disabled) 几种模式之间的转换
http://blog.sina.com.cn/s/blog_5aee9eaf0100y44q.html 在CentOS6.2 中安装intel 的c++和fortran 的编译器时,遇到来一个关于S ...
- @loj - 2461@ 「2018 集训队互测 Day 1」完美的队列
目录 @description@ @solution@ @part - 0@ @part - 1@ @accepted code@ @details@ @description@ 小 D 有 n 个 ...
- async/await运用-前端表单弹窗验证同步书写方式(React)
在前端项目中,我们经常会碰到这样的场景: 当前我们有一个表单需要填写,在完成表单填写后经过校验之后会弹出短信或者其他形式验证码,进行补充校验,然后一起提交给接口. 场景如下图: 当前为创建操作,编辑操 ...
- 树状数组(Binary Index Tree)
一维BIT(单点更新,区间求和): Problem - 1166 #include <iostream> #include <algorithm> #include <c ...
- DataTable CAST 成集合后,进行自定义排序再转换回DataTable
dt = dt.Rows.Cast<DataRow>().OrderBy(r => Convert.ToInt32(r["数量"])==0?1:0).ThenBy ...
- 模板—tarjan求割点
int dfn[MAXN],low[MAXN],cnt,root; bool iscut[MAXN]; void tarjan(int x) { dfn[x]=low[x]=++cnt; ; for( ...
- poj 3159 Candies (dij + heap)
3159 -- Candies 明明找的是差分约束,然后就找到这题不知道为什么是求1~n的最短路的题了.然后自己无聊写了一个heap,518ms通过. 代码如下: #include <cstdi ...
- cmd导入比较大的sql脚本
osql -S jack_c -d yourdb -U sa -P 123 -i E:\user.sql 注意: sql脚本里面一定要先创建数据库或者use到某个数据库,然后再cmd执行脚本