JDK1.8 Thread 源码分析

Posted 口袋里的Java技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK1.8 Thread 源码分析相关的知识,希望对你有一定的参考价值。

注释:

1 JVM允许一个应用同时并发运行多个线程

2 线程都有优先级,高优先级被执行的概率大于低优先级的线程;每个线程也会被标记为是否是守护线程;被某线程创建的子线程,与父线程有同样的优先级;守护线程只能由守护线程创建;

3 JVM启动时,通常会有一个非守护线程【main】(主线程)随之启动

4 两种方式去创建一个新的线程:1) 继承Thread 实现run

*     class PrimeThread extends Thread {
* long minPrime;
* PrimeThread(long minPrime) {
* this.minPrime = minPrime;
* }
*
* public void run() {
* // compute primes larger than minPrime
* }
* }
* PrimeThread p = new PrimeThread(143);
* p.start();

2)实现Runnable接口 实现run

class PrimeRun implements Runnable {
* long minPrime;
* PrimeRun(long minPrime) {
* this.minPrime = minPrime;
* }
*
* public void run() {
* // compute primes larger than minPrime
* }
* }
PrimeRun p = new PrimeRun(143);
* new Thread(p).start();

核心数据结构:

    private volatile char  name[];			//线程名称
private int priority; //线程优先级
private boolean single_step; //是否单步执行
private boolean stillborn = false; //虚拟机状态
private Runnable target; //将会被执行目标对象
private ThreadGroup group; //当前线程组对象,这里会用到 SecurityManger 如
// SecurityManager security = System.getSecurityManager(); security.getThreadGroup();
private ClassLoader contextClassLoader; //上下文类加载器
private static int threadInitNumber; //线程编号,线程编号每次++实现,++不是线程安全的,
//private static synchronized int nextThreadNum() {return threadInitNumber++; }
// ThreadLocal 用于实现线程内的数据共享,这里得单独讲 ThreadLocal 时候讲
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
private long stackSize; //线程操作时所需堆栈大小
private long tid; //线程id
//线程优先级
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
//中断阻塞
volatile Object parkBlocker;
private volatile Interruptible blocker;
public static native Thread currentThread();//当前线程
private long nativeParkEventPointer; //本地阻塞事件指针

核心方法:

1 yield:本质上 这个方法不建议在生产环境中使用,可以在测试benchmark时适度使用;因为线程主动让出cpu不一定能够能够明确的提升CPU的吞吐量

//线程让出当前调度 主动让步 和release属于执行完的被动让步
public static native void yield();

2 init类簇方法:

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) {
/* Determine if it's an applet or not */

/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}

/* If the security doesn't have a strong opinion of the matter
use the parent thread group. */
if (g == null) {
g = parent.getThreadGroup();
}
}

/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess();

/*
* Do we have the required permissions?
*/
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);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;

/* Set thread ID */
tid = nextThreadID();
}

3 start 和 run 所以 根据源码可以明显看出 线程启动的方法是start

public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();

/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);

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 */
}
}
}

private native void start0();

/**
* If this thread was constructed using a separate
* <code>Runnable</code> run object, then that
* <code>Runnable</code> object's <code>run</code> method is called;
* otherwise, this method does nothing and returns.
* <p>
* Subclasses of <code>Thread</code> should override this method.
*
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}

4 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 static boolean interrupted() {
return currentThread().isInterrupted(true);
}

/**
* Tests whether this thread has been interrupted. The <i>interrupted
* status</i> of the thread is unaffected by this method.
*
* <p>A thread interruption ignored because a thread was not alive
* at the time of the interrupt will be reflected by this method
* returning false.
*
* @return <code>true</code> if this thread has been interrupted;
* <code>false</code> otherwise.
* @see #interrupted()
* @revised 6.0
*/
public boolean isInterrupted() {
return isInterrupted(false);
}

/**
* Tests if some Thread has been interrupted. The interrupted state
* is reset or not based on the value of ClearInterrupted that is
* passed.
*/
private native boolean isInterrupted(boolean ClearInterrupted);

通过注释我们能发现 类静态方法是抹掉当前的中断标志位,成员方法仅是获取

5 join

     public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {//这里主要通过isAlive() 来判断目标线程是否已经执行完来决定 join
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
public State getState() {
// 通过这里判断线程状态
return sun.misc.VM.toThreadState(threadStatus);
}


以上是关于JDK1.8 Thread 源码分析的主要内容,如果未能解决你的问题,请参考以下文章

JDK1.8中ThreadLocal源码解析

JDK1.8中ThreadLocal源码解析

JDK1.8 FutureTask源码解读(Future模式)

FutureTask源码解析(JDK1.8)

JDK1.8 Thread类说明

JDK1.8 Thread类说明