盘一盘 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 ...
随机推荐
- docker search
命令:docker search [root@iZ943kh74qgZ ~]# docker search --help Usage: docker search [OPTIONS] TERM Sea ...
- OpenJudge_1936:All in All
描述 You have devised a new encryption technique which encodes a message by inserting between its char ...
- 16.libgdx根据配置文件生成布局(未完)
思路: screen分为普通和复杂两种,普通的功能大部分是页面跳转以及简单的crud数据,复杂的单独弄出来 跳转普通的screen,直接根据配置文件调整设置 <layouts> <l ...
- 字符缓冲流 Day20
package com.sxt.prac; /* * 缓冲流之字符缓冲流 defaultCharBufferSize = 8192; * 1.读入到程序 * 2.程序写到文件 * 3.采用循环边读边写 ...
- Redis源码解析:07压缩列表
压缩列表(ziplist)是列表键和哈希键的底层实现之一.当列表键只包含少量列表项,并且每个列表项要么是小整数值,要么是长度较短的字符串时:或者当哈希键只包含少量键值对,并且每个键值对的键和值要么是小 ...
- install tushare in python 3.6
install tushare (D:\Anaconda3) C:\Users\Administrator>pip install tushare Collecting tushare Down ...
- 从零学React Native之01创建第一个程序
本篇首发于简书 欢迎关注 上一篇文章是时候了解React Native了介绍了React Native.大家应该对React Native有个初步的认识. 接下来我们就可以初始化一个React Nat ...
- ansible api 通过python 方式调用
pip3 install ansible Linux下面安装 Windows 安装没成功 from ansible.parsing.dataloader import DataLoader #读取ya ...
- Open Source Software List: The Ultimate List
http://www.datamation.com/open-source/ Accessibility 1. The Accessibility Project The Business Value ...
- AtCoder Beginner Contest 075 C Bridge(割边)
求割边个数.Tarjan的板子.. #include <bits/stdc++.h> using namespace std; const int MAXN = 55; const int ...