Thread源码学习笔记,刚开始看,有些地方只懂个皮毛。之后深度理解了会再更改。
/**
* 学习Thread源码
*/
public class Thread implements Runnable{
/**
* 引进外部C函数。。registerNatives()的作用是注册本地C语言函数
*/
private static native void registerNatives() ;
static {
registerNatives();
}
private volatile String name ; //线程名字 volatile 类似于synchronized 是一种弱同步。。他为可见性,即改变后所有线程立即刷新最新的值
private int priority ; // 优先级 多线程优先级分为 高、中、低 值分别为10/5/1
private Thread threadQ ; //未知(网上也没有查到)
private long eetop ; //同未知
private boolean single_step ; //是否为单步执行。 可以理解句面意思但是不知道放在这里属性的具体作用
/**
* 是否为守护线程。 java线程存在两种: 用户线程和守护线程。 守护线程就是为用户线程服务的。
* 在一个实例中存在任何一个非守护线程还没有结束,那么所有守护线程会一直工作,直到非守护线程结束工作。(例如:GC垃圾回收器)
* Tip:可以写一段线程代码将其设置为守护线程看一下效果。
*/
private boolean daemon = false;
private boolean stillborn = false; //虚拟机状态。
private Runnable target ; //将被执行任务实体
private ThreadGroup group ; //线程组
private ClassLoader contextClassLoader ; //这个线程的上线文加载器
/**
* 线程继承的AccessControlContext
* 我没有搞清楚这个属性的真正意思。我看了一下AccessControlContext的源码,他的官方解释为:“用于根据他封装的上下文做出系统资源访问决策。
* 不过我在网上查到了一种解释“这里是继承AccessControlContext类,这里才是真正的线程,而得到线程的方法就是:
* this.inheritedAccessControlContext = AccessController.getContext();"
*/
private AccessControlContext inheritedAccessControlContext;
/**
* 根据属性名就可以看出来,threadInitNumber线程初始编号
* 下面的是下一个线程的编号,为自增
* 在线程初始化把这个number给线程的名字(具体形式为“Thread-”+number 这个格式。 可以用thead.getName()看一下
*/
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
ThreadLocal.ThreadLocalMap threadLocals = null; //ThreadLocal.ThreadLocalMap映射表
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; //这个还是要先了解ThreadLocal然后再学习ThreadLocalMap。这里不在写了,太多了...
private long stackSize ; //堆栈空间,一般不用管 JVM会默认分配
private long nativeParkEventPointer; //未知
private long tid; //线程ID
private static long threadSeqNumber; //用来生成线程ID类似于上面提到的编号
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
private volatile int threadStatus = 0; //线程状态,默认为0(未启动)
/**
* 下面的parkBlocker、blocker、blockedOn只知道表面意思,具体写不出来,后面还要好好学习下
*/
volatile Object parkBlocker; // 中断阻塞器:当线程发生IO中断时,需要在线程被设置为中断状态后调用该对象的interrupt方法
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 static native Thread currentThread(); //当前线程 返回当前线程对象
/**
* 线程让步 即线程使用该方法后放弃cpu时间,从运行状态重新变成就绪状态
* 注意让步是让“自己”和“其他线程” 。。即自己放弃了cpu但是自己还是可以获取的,,自己可以重新竞争cpu
* 所以并不是线程让步后,其他与之同级优先级的线程一定可以得到cpu
*/
public static native void yield();
/**
* 睡眠 暂停线程 使用sleep的线程会在规定的时间内放弃cpu 让cpu去执行其他线程 时间到后睡眠的线程重新回到“就绪状态”(而不是运行状态)
* 但是如果该线程进入了同步做,sleep不会释放锁。意味着其他被同步锁挡住的线程同样不能运行
* millis是毫秒 nanos是纳秒
*/
public static native void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos) throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
//nanos >= 500000(纳秒大于500000毫秒加1) 或者 nanos != 0 && millis == 0 (纳秒不等于0并且毫秒等于0是毫秒加1)
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
/**
* 线程初始化 包括后面的线程构造都是调用init线程初始化
* 建议看一下初始化方法里面的代码
* g 线程组 target 被调用布标方法的runnable实体对象
* name 线程名 stackSize 栈空间
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
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();
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 (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
this.stackSize = stackSize;
tid = nextThreadID();
}
/**
* 一些构造 里面都调用了init方法
*/
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, false);
}
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);
}
/**
* 启动线程
*/
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();
/**
* 线程结束时清理(clean up)
*/
private void exit() {
if (group != null) {
group.threadTerminated(this);
group = null;
}
target = null;
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
/**
* 线程中断 中断并不意味着线程立即结束
* 中断的结果线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于这个程序本身。
* 线程会不时地检测这个中断标示位,以判断线程是否应该被中断(中断标示值是否为true)。
*/
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0();
b.interrupt(this);
return;
}
}
interrupt0();
}
/**
* 是否中断
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);
public final native boolean isAlive(); //判断线程是否活着
/**
* 设置优先级
*/
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
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 synchronized void setName(String name) {
checkAccess();
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
if (threadStatus != 0) {
setNativeName(name);
}
}
/**
* 得到线程名字
*/
public final String getName() {
return name;
}
/**
* 得到线程组
* @return
*/
public final ThreadGroup getThreadGroup() {
return group;
}
/**
* 返回活动线程的当前线程的线程组中的数量。
*/
public static int activeCount() {
return currentThread().getThreadGroup().activeCount();
}
/**
*将当前线程的线程组及其子组中的每个活动线程复制到指定的数组中。
*/
public static int enumerate(Thread tarray[]) {
return currentThread().getThreadGroup().enumerate(tarray);
}
/**
* 举个例子介绍一下join
* A线程调用了线程B 然后B.join(),则只有线程A会进入挂起状态,当线程B执行完成后,A线程才会继续执行
* 同时api还提供了millis、nanos为为参数的join方法 可以看一下源码,类似上面提到的sleep一个近似的时间
*
*/
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;
}
}
}
public final synchronized void join(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
join(millis);
}
/**
* 打印一个追踪当前线程的堆栈
*/
public static void dumpStack() {
new Exception("Stack trace").printStackTrace();
}
/**
* 设置为守护线程
*/
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
/**
* 是否为守护线程
*/
public final boolean isDaemon() {
return daemon;
}
/**
*检查线程是否有修改权限
* 具体可以看一下SecurityManager源码
*/
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
/**
* 返回该线程的上下文 ClassLoader。
* 上下文 ClassLoader 由线程创建者提供,供运行于该线程中的代码在加载类和资源时使用。
* 如果未设定,则默认为父线程的 ClassLoader 上下文。原始线程的上下文 ClassLoader 通常设定为用于加载应用程序的类加载器。
* 首先,上下文 ClassLoader不是null,然后有安全管理器,
* 则通过 ClassLoader的 checkClassLoaderPermission方法,查看是否可以获取上下文 ClassLoader。
*/
@CallerSensitive
public ClassLoader getContextClassLoader() {
if (contextClassLoader == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(contextClassLoader,
Reflection.getCallerClass());
}
return contextClassLoader;
}
/**
* 设置该线程的上下文 ClassLoader。
* 上下文 ClassLoader 可以在创建线程设置,并允许创建者在加载类和资源时向该线程中运行的代码提供适当的类加载器。
* 首先,如果有安全管理器,则通过 RuntimePermission("setContextClassLoader") 权限调用其 checkPermission 方法,
* 查看是否可以设置上下文 ClassLoader。
*/
public void setContextClassLoader(ClassLoader cl) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
contextClassLoader = cl;
}
//Thread的源码基本要完了,后面还有一些线程堆栈跟踪数组、跟踪映射还有一些比较杂的东西。。学习了再记录出来
//还没弄的太懂