线程池系列源码分析
1.Thread源码分析
-
// Runnable -> run public class Thread implements Runnable {
1.字段
// 线程名称
private volatile String name;
// 优先级
private int priority;
// 线程
private Thread threadQ;
//
private long eetop;
/* 是否单步执行此线程 */
private boolean single_step;
/* 是否为守护线程 */
private boolean daemon = false;
/* JVM 状态 */
private boolean stillborn = false;
/* 将要运行什么 */
private Runnable target;
/* 该线程的组 */
private ThreadGroup group;
/* 此线程的上下文ClassLoader */
private ClassLoader contextClassLoader;
/* 该线程的继承的AccessControlContext */
private AccessControlContext inheritedAccessControlContext;
/* 用于自动编号匿名线程 */
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/*
* 此线程请求的堆栈大小,如果创建者未指定堆栈大小,则为0。 由VM决定使用此编号执行任何操作。 一些虚拟机将忽略它。
*/
private long stackSize;
/*
* JVM私有状态在本地线程终止后仍然存在。
*/
private long nativeParkEventPointer;
/*
* 线程 ID
*/
private long tid;
/* 用于生成线程ID */
private static long threadSeqNumber;
/*
* 工具的Java线程状态,已初始化以指示线程“尚未启动”
*/
private volatile int threadStatus = 0;
private final Object blockerLock = new Object();
/**
* 线程可以具有的最低优先级。
*/
public final static int MIN_PRIORITY = 1;
/**
* 分配给线程的默认优先级。
*/
public final static int NORM_PRIORITY = 5;
/**
* 线程可以具有的最大优先级。
*/
public final static int MAX_PRIORITY = 10;
2.构造方法
/**
* @param ThreadGroup group
* @param Runnable target
* @param name
* @param stackSize 此线程请求堆栈大小
* @param acc 符合要继承的AccessControlContext;如果为null,则为AccessController.getContext()
* @param 如果{@code true},则从构造线程继承可继承线程本地变量的初始值
*/
!-----------------!
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);
}
// 初始化方法
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) {
/* 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方法
public synchronized void start() {
/**
*主方法线程或“系统”不调用此方法
*由VM创建/设置的组线程。添加的任何新功能
*将来可能还必须将此方法添加到VM。
*
* 零状态值对应于状态“ NEW”。
*/
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) {
/* 没做什么。如果start0抛出Throwable,则
它将被传递到调用堆栈 */
}
}
}
void add(Thread t) {
synchronized (this) {
if (destroyed) {
throw new IllegalThreadStateException();
}
if (threads == null) {
threads = new Thread[4];
} else if (nthreads == threads.length) {
threads = Arrays.copyOf(threads, nthreads * 2);
}
threads[nthreads] = t;
// This is done last so it doesn't matter in case the
// thread is killed
nthreads++;
// 线程现在是该组的正式成员,即使它可能已经启动也可能尚未启动。 这将防止该组被破坏,因此未启动的线程数为递减。
nUnstartedThreads--;
}
}
4.sleep方法
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");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
5.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);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
6.setPriority方法
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);
}
}
7.setName方法
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);
}
}
8.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();
}
10.内部类
10.1 State枚举
public enum State {
/**
* 尚未启动的线程的线程状态
*/
NEW,
/**
*可运行线程的线程状态。可运行线程
*状态正在Java虚拟机中执行,但它可能
*等待来自操作系统的其他资源
*如处理器。
*/
RUNNABLE,
/**
*线程的线程状态被阻塞,等待监视器锁定。
*处于阻塞状态的线程正在等待监视器锁定
*输入同步块/方法或
*调用后重新输入同步块/方法
* {@link Object#wait()Object.wait}。
*/
BLOCKED,
/**
*等待线程的线程状态。
*由于调用其中一个线程,线程处于等待状态
*以下方法:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>处于等待状态的线程正在等待另一个线程执行特定操作。
*
* 例如,一个调用了<tt> Object.wait()</ tt>的线程
* 在对象上正在等待另一个线程调用
* <tt> Object.notify()</ tt>或<tt> Object.notifyAll()</ tt>
* 那个对象。名为<tt> Thread.join()</ tt>的线程
* 正在等待指定线程终止。
*/
WAITING,
/**
* 具有指定等待时间的等待线程的线程状态。
* 线程由于调用了以下之一而处于定时等待状态
* 以下方法具有指定的正等待时间:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* 终止线程的线程状态。
* 线程已完成执行。
*/
TERMINATED;
}
2.线程池源码分析
-
// AbstractExectuorService -> ExecutorService -> Executor(executor) public class ThreadPoolExecutor extends AbstractExecutorService {
1.字段
/**
*主池控制状态ctl是原子整数包装
*两个概念领域
* workerCount,指示有效线程数
* runState,指示是否正在运行,正在关闭等
*
*为了将它们打包为一个int,我们将workerCount限制为
*(2 ^ 29)-1(约5亿)个线程而不是(2 ^ 31)-1(2
*十亿)。如果这是一个问题
*将来,该变量可以更改为AtomicLong,
*和下面的移位/遮罩常数已调整。但是直到需要
*出现,此代码使用int会更快,更简单。
*
* workerCount是已经工作的工人数
*允许启动而不允许停止。该值可能是
*与实际活动线程数暂时不同,
*例如,当ThreadFactory无法创建线程时,
*问,退出线程仍在执行时
*终止之前记账。用户可见的池大小为
*报告为当前设置的工人人数。
*
* runState提供主要的生命周期控制,并具有以下值:
*
*Running:接受新任务并处理排队的任务
*SHUTDOWN:不接受新任务,但处理排队的任务
*STOP:不接受新任务,不处理排队的任务,并中断正在进行的任务
*TIDYING:所有任务已终止,workerCount为零,线程过渡到TIDYING状态,将运行terminated() 挂钩方法
*TREMINATED:terminate()已完成
*
*这些值之间的数字顺序很重要,以允许
*有序比较。 runState单调增加
*时间,但不必打到每个状态。过渡是:
*
*运行->关闭 - (RUNNING -> SHUTDOWN)
*在调用shutdown()时,可能隐式在finalize()中
*(正在运行或关闭)->停止 - (RUNNING or SHUTDOWN) -> STOP
*在调用shutdownNow()时
*关闭->整理 - SHUTDOWN -> TIDYING
*当队列和池都为空时
*停止->整理 - STOP -> TIDYING
*当池为空时
*整理->已终止 - TIDYING -> TERMINATED
*当Terminate()挂钩方法完成时
*
*在awaitTermination()中等待的线程将在
*状态达到TERMINATED。
*
*检测从SHUTDOWN到TIDYING的过渡较少
*比您想要的简单,因为队列可能会变成
*在非空状态后为空,反之亦然;
*我们只有在看到它为空后看到
* workerCount为0(有时需要重新检查-请参阅
*下方)。
*/
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
/**
* 用于保留任务并移交给工作线程的队列。
* 我们不要求workQueue.poll()返回null必然意味着workQueue.isEmpty(),因此仅依靠isEmpty来查看队列是否为空(例如,在确定是否从SHUTDOWN过渡到TIDYING时必须这样做)。
* 这可容纳诸如DelayQueues之类的专用队列,这些队列允许poll()返回null,即使它可能在延迟到期后稍后返回non-null。
*/
private final BlockingQueue<Runnable> workQueue;
/**
* 上锁工人进入工作场所并进行相关簿记。
* 虽然我们可以使用某种并发集,但事实证明,通常最好使用锁。
* 原因之一是它可以对interruptIdleWorkers进行序列化,从而避免了不必要的中断风暴,尤其是在关机期间。
* 否则,退出线程将同时中断那些尚未中断的线程。 它还简化了一些相关的统计数据,如largePoolSize等。
* 我们还在shutdown和shutdownNow上保留mainLock,以确保在设置工人权限稳定的同时分别检查中断权限和实际中断权限。
*/
private final ReentrantLock mainLock = new ReentrantLock();
/**
* 集包含池中的所有工作线程。 仅在按住mainLock时访问。
*/
private final HashSet<Worker> workers = new HashSet<Worker>();
/**
* 等待条件以支持awaitTermination
*/
private final Condition termination = mainLock.newCondition();
/**
* 跟踪达到的最大池大小。 仅在下访问mainLock。
*/
private int largestPoolSize;
/**
* 计数器完成的任务。 仅在终止工作线程时更新。 仅在mainLock下访问。
*/
private long completedTaskCount;
/*
* All user control parameters are declared as volatiles so that
* ongoing actions are based on freshest values, but without need
* for locking, since no internal invariants depend on them
* changing synchronously with respect to other actions.
*/
/**
* Factory for new threads. All threads are created using this
* factory (via method addWorker). All callers must be prepared
* for addWorker to fail, which may reflect a system or user's
* policy limiting the number of threads. Even though it is not
* treated as an error, failure to create threads may result in
* new tasks being rejected or existing ones remaining stuck in
* the queue.
*
* We go further and preserve pool invariants even in the face of
* errors such as OutOfMemoryError, that might be thrown while
* trying to create threads. Such errors are rather common due to
* the need to allocate a native stack in Thread.start, and users
* will want to perform clean pool shutdown to clean up. There
* will likely be enough memory available for the cleanup code to
* complete without encountering yet another OutOfMemoryError.
*/
private volatile ThreadFactory threadFactory;
/**
* 在执行饱和或关闭时调用处理程序。
*/
private volatile RejectedExecutionHandler handler;
/**
* 空闲线程等待工作的超时时间(以纳秒为单位)。当存在多个corePoolSize或allowCoreThreadTimeOut时,线程使用此超时。 否则,他们将永远等待新的工作。
*/
private volatile long keepAliveTime;
/**
* 如果为false(默认),则即使处于空闲状态,核心线程也保持活动状态。
* 如果为true,则核心线程使用keepAliveTime来超时等待工作。
*/
private volatile boolean allowCoreThreadTimeOut;
/**
*除非设置allowCoreThreadTimeOut,否则核心池大小是保持活动(不允许超时等)工作的最小数量,在这种情况下,最小值为零。
*/
private volatile int corePoolSize;
/**
* 最大池大小。 请注意,实际最大值在内部受“容量”限制。
*/
private volatile int maximumPoolSize;
/* 执行终结器时使用的上下文,或者为null。 */
private final AccessControlContext acc;
2.构造方法
/**
* @param ThreadGroup group
* @param Runnable target
* @param name
* @param stackSize 此线程请求堆栈大小
* @param acc 符合要继承的AccessControlContext;如果为null,则为AccessController.getContext()
* @param 如果{@code true},则从构造线程继承可继承线程本地变量的初始值
*/
!-----------------!
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);
}
// 初始化方法
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) {
/* 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方法
public synchronized void start() {
/**
*主方法线程或“系统”不调用此方法
*由VM创建/设置的组线程。添加的任何新功能
*将来可能还必须将此方法添加到VM。
*
* 零状态值对应于状态“ NEW”。
*/
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) {
/* 没做什么。如果start0抛出Throwable,则
它将被传递到调用堆栈 */
}
}
}
void add(Thread t) {
synchronized (this) {
if (destroyed) {
throw new IllegalThreadStateException();
}
if (threads == null) {
threads = new Thread[4];
} else if (nthreads == threads.length) {
threads = Arrays.copyOf(threads, nthreads * 2);
}
threads[nthreads] = t;
// This is done last so it doesn't matter in case the
// thread is killed
nthreads++;
// 线程现在是该组的正式成员,即使它可能已经启动也可能尚未启动。 这将防止该组被破坏,因此未启动的线程数为递减。
nUnstartedThreads--;
}
}
4.sleep方法
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");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
5.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);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
6.setPriority方法
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);
}
}
7.setName方法
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);
}
}
8.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();
}
10.内部类
10.1 DefaultThreadFactory
static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
来源:oschina
链接:https://my.oschina.net/u/4182062/blog/3121607