其他 源码解析 https://blog.csdn.net/qq_32726809/article/category/8035214
1类的声明
public
class Thread implements Runnable
- 实现了Runnable接口
- 在程序开发中只要是多线程肯定永远以实现Runnable接口为主。
1.1Runnable 说明
public interface Runnable {
public abstract void run();
}
只有一个run的方法。
2常用属性
private volatile String name; /*线程名*/
private int priority; /* 优先级*/
/* Whether or not to single_step this thread. */
private boolean single_step;/*是否单步执行*/
/* Whether or not the thread is a daemon thread. */
private boolean daemon = false;/*是否守护线程*/
/* JVM state */
private boolean stillborn = false;/*虚拟机状态*/
/* What will be run. */
private Runnable target;/*将会被执行的runnable*/
/* The group of this thread */
private ThreadGroup group;/*线程组*/
/* The context ClassLoader for this thread *//**/
private ClassLoader contextClassLoader;
/* The inherited AccessControlContext of this thread */
private AccessControlContext inheritedAccessControlContext;
/* For autonumbering anonymous threads. */
private static int threadInitNumber;/*线程的自动编号*/
private static synchronized int nextThreadNum() {/*-----------------------------------------1*/
return threadInitNumber++;
}
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/*
* The requested stack size for this thread, or 0 if the creator did
* not specify a stack size. It is up to the VM to do whatever it
* likes with this number; some VMs will ignore it.
*/
private long stackSize;
/*
* JVM-private state that persists after native thread termination.
*/
private long nativeParkEventPointer;
/*
* Thread ID
*/
private long tid;/*线程id,每个线程都会专属的id*/
/* For generating thread ID */
private static long threadSeqNumber;
/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
private volatile int threadStatus = 0;/*线程状态,1.8新加的,默认是启动状态*/
private static synchronized long nextThreadID() { /*下个线程id*/
return ++threadSeqNumber;
}
/**
* The argument supplied to the current call to
* java.util.concurrent.locks.LockSupport.park.
* Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
* Accessed using java.util.concurrent.locks.LockSupport.getBlocker
*/
volatile Object parkBlocker;
/* The object in which this thread is blocked in an interruptible I/O
* operation, if any. The blocker's interrupt method should be invoked
* after setting this thread's interrupt status.
*/
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
/* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
*/
void blockedOn(Interruptible b) {
synchronized (blockerLock) {
blocker = b;
}
}
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;/*线程最小优先级*/
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;/*默认优先级*/
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;/*最高优先级*/
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
- Runable 个人感觉就像汽车里的货物,而Thread就像汽车
- 1处这个方法有 synchronized 修饰,是线程安全的
- 线程六状态:
- NEW
- 创建后未分配资源的状态,没有start的线程
- RUNNABLE
- 可运行。一旦调用start()方法,线程进入Runnable状态,此时,该线程可能在运行,也可能没有运行。这取决于操作系统给线程提供的运行的时间。
- 线程被分配完资源后,便进入待准备状态,可运行,等待cpu的执行
- BLOCKED
- 被阻塞。当一个线程获取一个内部的对象锁,而这个锁被其他线程持有,则该线程进入阻塞状态。当所有线程释放掉该锁,且线程调度器允许该线程持有这个对象锁时,该线程进入到非阻塞状态。
- 被同步块阻塞或者io阻塞
- WAITING
- 等待,等待被别人唤醒
- TIMED_WAITING
- 时间等待,睡够时间了,自己就起来了。
- TERMINATED
- 被终止。一般有两种情况:run()方法正常执行完毕而正常死亡。另一种情况是:没有捕获的异常终止了run()方法而意外死亡。
- 正常执行完毕,或者异常中断
3构造函数
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);
}
可以看出,线程调用的都是 init(group, target, name, stackSize);方法
3.1init(group, target, name, stackSize)
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
3.2init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals)
- g 线程组
- target 要执行的继承Runnable接口的类的对象
- name 线程的名字
- stacksize 申请的堆的大小
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();/*-------------------------1*/
SecurityManager security = System.getSecurityManager();/*-------------------------2*/
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) {/*-------------------------3*/
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();/*-------------------------4*/
}
}
/* 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();/*-------------------------5*/
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();
}
- 1处的意思是后去调用这个线程对象的线程
- 2处的意思是获取系统的安全管理
- 此处解释原文如下 if a security manager has already been established for the current application, then that security manager is returned; otherwise, null is returned.
- 如果系统设置了安全管理器,这里就会返回,如果没有就会返回null
- 3处的意思是如果安全管理不为空,那么返回适当的线程组
- 4处的意思是如果安全管理器对线程组没要求,那么返回调用这个线程对象的线程组。
3.3start()
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)/*---------------------1*/
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);/*---------------------2*/
boolean started = false;
try {
start0();/*---------------------3*/
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();
- 1 处的意思是 如果不是 new 状态 则 不能启动
- 2 处的意思是 把线程放到线程组中 ,下一篇会详细介绍线程组
- 3 底层代码实现启动
3.4 run()
public void run() {
if (target != null) {
target.run();
}
}
- 如果有Runnable 的对象,就执行 对象Runnable的run操作
3.5 exit()
private void exit() {
if (group != null) {
group.threadTerminated(this);/*----------1*/
group = null;
}
/* Aggressively null out all reference fields: see bug 4006245 */
target = null;
/* Speed the release of some of these resources */
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
void threadTerminated(Thread t) {
synchronized (this) {
remove(t);
if (nthreads == 0) {
notifyAll();
}
if (daemon && (nthreads == 0) &&
(nUnstartedThreads == 0) && (ngroups == 0))
{
destroy();
}
}
}
- 1处的意思是,通知线程组 这个线程已经停止 原文: Notifies the group that the thread t has terminated. Destroy the group if all of the following conditions are true: this is a daemon thread group; there are no more alive or unstarted threads in the group; there are no subgroups in this thread group.
- 这里需要说是如果线程是守护线程,并且这个线程组中没有存货的线程或者新的线程创建,并且,没有子组在这个线程组里,则删除这个线程组。这是 Threadgroup 中的方法,稍后会对这个做详细解释
- 这个方法会变量置为空,加快资源释放。
- 在线程运行完后会调用这个方法,一般是run运行完后
3.6stop()
- stop这个方法,源码已经过时了,原因是因为,stop方法十分的暴力,会造成一些很难处理的问题。
3.7 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();
}
3.8 isAlive();
判断一个线程是否活着。
3.9 setPriority(int newPriority)
设置优先级
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;
}
用来设置优先级
3.10 join(long millis)
阻塞当前线程,(其实了类似于 ajax 中的同步,等请求结束后,才能往下走)这里就是,线程结束后才能往下走
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);/*----------1*/
now = System.currentTimeMillis() - base;
}
}
}
- 1处的意思是等待 delay长的时间, 如果 now <0 则跳出循环
3.11 setDaemon
用来设置守护线程
public final void setDaemon(boolean on) {
checkAccess();/*------1*/
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
- 1处的意思运行的线程是否有权修改这个线程,这个判断来自安全管理器
3.12 toString
返回的线程第一个是名字,第二个是优先级,第三个是组的名字
public String toString() {
ThreadGroup group = getThreadGroup();
if (group != null) {
return "Thread[" + getName() + "," + getPriority() + "," +
group.getName() + "]";
} else {
return "Thread[" + getName() + "," + getPriority() + "," +
"" + "]";
}
}
3.13 getContextClassLoader
- 获取上下文类加载器
- 类加载器就是把字节码 加载到 jvm虚拟机中
- 一个ClassLoader创建时如果没有指定parent,那么它的parent默认就是AppClassLoader。
public ClassLoader getContextClassLoader() {
if (contextClassLoader == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(contextClassLoader,
Reflection.getCallerClass());
}
return contextClassLoader;
}
3.14 getStackTrace()
获取线程的堆栈转储列表
- 查了很多的资料,没有明确的说明,后续若有了解,会继续更新 网上的例子 http://www.cnblogs.com/whsa/p/4374465.html
public StackTraceElement[] getStackTrace() {
if (this != Thread.currentThread()) {
// check for getStackTrace permission
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
}
// optimization so we do not call into the vm for threads that
// have not yet started or have terminated
if (!isAlive()) {
return EMPTY_STACK_TRACE;
}
StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
StackTraceElement[] stackTrace = stackTraceArray[0];
// a thread that was alive during the previous isAlive call may have
// since terminated, therefore not having a stacktrace.
if (stackTrace == null) {
stackTrace = EMPTY_STACK_TRACE;
}
return stackTrace;
} else {
// Don't need JVM help for current thread
return (new Exception()).getStackTrace();
}
}