JDK原始碼分析——Thread
阿新 • • 發佈:2019-01-23
說實話,這部分東西太多了,而且涉及到JNI和JVM的東西,先只分析一小部分,以後再補上
//runnable是隻有一個run函式的介面 public class Thread implements Runnable { /* Make sure registerNatives is the first thing <clinit> does. */ //jni private static native void registerNatives(); static { registerNatives(); } private char name[]; private int priority; private Thread threadQ; private long eetop; /* 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; /* 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; /*用於分配執行緒的id號,注意這裡的synchronized*/ private static synchronized int nextThreadNum() { 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; /* For generating thread ID */ private static long threadSeqNumber; /* Java thread status for tools, * initialized to indicate thread 'not yet started' */ private int threadStatus = 0; /*分配執行緒內部的執行緒號*/ private static synchronized long nextThreadID() { 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 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; /* If stop was called before start */ private boolean stopBeforeStart; /* Remembered Throwable from stop before start */ private Throwable throwableFromStop; /* Whether or not the Thread has been completely constructed; * init or clone method has successfully completed */ private volatile Thread me; // null /*下面是一些執行緒控制的jni*/ /** * Returns a reference to the currently executing thread object. * * @return the currently executing thread. */ public static native Thread currentThread(); /** * Causes the currently executing thread object to temporarily pause * and allow other threads to execute. */ public static native void yield(); /** * Causes the currently executing thread to sleep (temporarily cease * execution) for the specified number of milliseconds, subject to * the precision and accuracy of system timers and schedulers. The thread * does not lose ownership of any monitors. * * @param millis the length of time to sleep in milliseconds. * @exception InterruptedException if any thread has interrupted * the current thread. The <i>interrupted status</i> of the * current thread is cleared when this exception is thrown. * @see Object#notify() */ public static native void sleep(long millis) throws InterruptedException; /** * Causes the currently executing thread to sleep (cease execution) * for the specified number of milliseconds plus the specified number * of nanoseconds, subject to the precision and accuracy of system * timers and schedulers. The thread does not lose ownership of any * monitors. * * @param millis the length of time to sleep in milliseconds. * @param nanos 0-999999 additional nanoseconds to sleep. * @exception IllegalArgumentException if the value of millis is * negative or the value of nanos is not in the range * 0-999999. * @exception InterruptedException if any thread has interrupted * the current thread. The <i>interrupted status</i> of the * current thread is cleared when this exception is thrown. * @see Object#notify() */ 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的jni*/ sleep(millis); } /** * Initializes a Thread. * * @param g the Thread group * @param target the object whose run() method gets called * @param name the name of the new Thread * @param stackSize the desired stack size for the new thread, or * zero to indicate that this parameter is to be ignored. */ private void init(ThreadGroup g, Runnable target, String name, long stackSize) { /*當前的執行緒會成為建立後的執行緒的父執行緒*/ 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(); this.name = name.toCharArray(); /*執行緒上下文的獲取*/ if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = AccessController.getContext(); /*設定執行緒的執行函式*/ this.target = target; /*設定執行緒的優先順序*/ setPriority(priority); if (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(); /*設定自身,標記已經初始化*/ this.me = this; } /** * Returns a clone if the class of this object is {@link Cloneable Cloneable}. * * @return a clone if the class of this object is {@code Cloneable} * * @throws CloneNotSupportedException * if this method is invoked on a class that does not * support {@code Cloneable} */ /*過載object的clone函式*/ @Override protected Object clone() throws CloneNotSupportedException { Thread t; synchronized(this) { t = (Thread) super.clone(); /*分配一個新的執行緒號*/ t.tid = nextThreadID(); t.parkBlocker = null; t.blocker = null; t.blockerLock = new Object(); t.threadLocals = null; /**/ group.checkAccess(); if (threadStatus == 0) { group.addUnstarted(); } t.setPriority(priority); final Thread current = Thread.currentThread(); if (current.inheritableThreadLocals != null) t.inheritableThreadLocals = ThreadLocal.createInheritedMap(current.inheritableThreadLocals); } t.me = t; return t; } /*************************一大片構造器即將來襲*****************************/ /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(null, null,</code> * <i>gname</i><code>)</code>, where <b><i>gname</i></b> is * a newly generated name. Automatically generated names are of the * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. * * @see #Thread(ThreadGroup, Runnable, String) */ public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); } /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(null, target,</code> * <i>gname</i><code>)</code>, where <i>gname</i> is * a newly generated name. Automatically generated names are of the * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. * * @param target the object whose <code>run</code> method is called. * @see #Thread(ThreadGroup, Runnable, String) */ public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); } /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(group, target,</code> * <i>gname</i><code>)</code>, where <i>gname</i> is * a newly generated name. Automatically generated names are of the * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. * * @param group the thread group. * @param target the object whose <code>run</code> method is called. * @exception SecurityException if the current thread cannot create a * thread in the specified thread group. * @see #Thread(ThreadGroup, Runnable, String) */ public Thread(ThreadGroup group, Runnable target) { init(group, target, "Thread-" + nextThreadNum(), 0); } /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(null, null, name)</code>. * * @param name the name of the new thread. * @see #Thread(ThreadGroup, Runnable, String) */ public Thread(String name) { init(null, null, name, 0); } /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(group, null, name)</code> * * @param group the thread group. * @param name the name of the new thread. * @exception SecurityException if the current thread cannot create a * thread in the specified thread group. * @see #Thread(ThreadGroup, Runnable, String) */ public Thread(ThreadGroup group, String name) { init(group, null, name, 0); } /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(null, target, name)</code>. * * @param target the object whose <code>run</code> method is called. * @param name the name of the new thread. * @see #Thread(ThreadGroup, Runnable, String) */ public Thread(Runnable target, String name) { init(null, target, name, 0); } /** * Allocates a new <code>Thread</code> object so that it has * <code>target</code> as its run object, has the specified * <code>name</code> as its name, and belongs to the thread group * referred to by <code>group</code>. * <p> * If <code>group</code> is <code>null</code> and there is a * security manager, the group is determined by the security manager's * <code>getThreadGroup</code> method. If <code>group</code> is * <code>null</code> and there is not a security manager, or the * security manager's <code>getThreadGroup</code> method returns * <code>null</code>, the group is set to be the same ThreadGroup * as the thread that is creating the new thread. * * <p>If there is a security manager, its <code>checkAccess</code> * method is called with the ThreadGroup as its argument. * <p>In addition, its <code>checkPermission</code> * method is called with the * <code>RuntimePermission("enableContextClassLoaderOverride")</code> * permission when invoked directly or indirectly by the constructor * of a subclass which overrides the <code>getContextClassLoader</code> * or <code>setContextClassLoader</code> methods. * This may result in a SecurityException. * <p> * If the <code>target</code> argument is not <code>null</code>, the * <code>run</code> method of the <code>target</code> is called when * this thread is started. If the target argument is * <code>null</code>, this thread's <code>run</code> method is called * when this thread is started. * <p> * The priority of the newly created thread is set equal to the * priority of the thread creating it, that is, the currently running * thread. The method <code>setPriority</code> may be used to * change the priority to a new value. * <p> * The newly created thread is initially marked as being a daemon * thread if and only if the thread creating it is currently marked * as a daemon thread. The method <code>setDaemon </code> may be used * to change whether or not a thread is a daemon. * * @param group the thread group. * @param target the object whose <code>run</code> method is called. * @param name the name of the new thread. * @exception SecurityException if the current thread cannot create a * thread in the specified thread group or cannot * override the context class loader methods. * @see Runnable#run() * @see #run() * @see #setDaemon(boolean) * @see #setPriority(int) * @see ThreadGroup#checkAccess() * @see SecurityManager#checkAccess */ public Thread(ThreadGroup group, Runnable target, String name) { init(group, target, name, 0); } /** * Allocates a new <code>Thread</code> object so that it has * <code>target</code> as its run object, has the specified * <code>name</code> as its name, belongs to the thread group referred to * by <code>group</code>, and has the specified <i>stack size</i>. * * <p>This constructor is identical to {@link * #Thread(ThreadGroup,Runnable,String)} with the exception of the fact * that it allows the thread stack size to be specified. The stack size * is the approximate number of bytes of address space that the virtual * machine is to allocate for this thread's stack. <b>The effect of the * <tt>stackSize</tt> parameter, if any, is highly platform dependent.</b> * * <p>On some platforms, specifying a higher value for the * <tt>stackSize</tt> parameter may allow a thread to achieve greater * recursion depth before throwing a {@link StackOverflowError}. * Similarly, specifying a lower value may allow a greater number of * threads to exist concurrently without throwing an {@link * OutOfMemoryError} (or other internal error). The details of * the relationship between the value of the <tt>stackSize</tt> parameter * and the maximum recursion depth and concurrency level are * platform-dependent. <b>On some platforms, the value of the * <tt>stackSize</tt> parameter may have no effect whatsoever.</b> * * <p>The virtual machine is free to treat the <tt>stackSize</tt> * parameter as a suggestion. If the specified value is unreasonably low * for the platform, the virtual machine may instead use some * platform-specific minimum value; if the specified value is unreasonably * high, the virtual machine may instead use some platform-specific * maximum. Likewise, the virtual machine is free to round the specified * value up or down as it sees fit (or to ignore it completely). * * <p>Specifying a value of zero for the <tt>stackSize</tt> parameter will * cause this constructor to behave exactly like the * <tt>Thread(ThreadGroup, Runnable, String)</tt> constructor. * * <p><i>Due to the platform-dependent nature of the behavior of this * constructor, extreme care should be exercised in its use. * The thread stack size necessary to perform a given computation will * likely vary from one JRE implementation to another. In light of this * variation, careful tuning of the stack size parameter may be required, * and the tuning may need to be repeated for each JRE implementation on * which an application is to run.</i> * * <p>Implementation note: Java platform implementers are encouraged to * document their implementation's behavior with respect to the * <tt>stackSize parameter</tt>. * * @param group the thread group. * @param target the object whose <code>run</code> method is called. * @param name the name of the new thread. * @param stackSize the desired stack size for the new thread, or * zero to indicate that this parameter is to be ignored. * @exception SecurityException if the current thread cannot create a * thread in the specified thread group. * @since 1.4 */ public Thread(ThreadGroup group, Runnable target, String name, long stackSize) { init(group, target, name, stackSize); } /** * Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread. * <p> * The result is that two threads are running concurrently: the * current thread (which returns from the call to the * <code>start</code> method) and the other thread (which executes its * <code>run</code> method). * <p> * It is never legal to start a thread more than once. * In particular, a thread may not be restarted once it has completed * execution. * * @exception IllegalThreadStateException if the thread was already * started. * @see #run() * @see #stop() */ /*啟動執行緒*/ 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 || this != me) throw new IllegalThreadStateException(); /*新增到執行緒組*/ group.add(this); /*Java啊!你也沒有能力呼叫系統呼叫啊,還得小JNI來呼叫系統呼叫,建立真正的執行緒啊*/ start0(); /*如果需要不立即執行,就讓他停下來*/ if (stopBeforeStart) { stop0(throwableFromStop); } } 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) */ //執行緒的執行體,要麼new Thread(Runnable)設定target,要麼就得過載這個函式啊 //Java得多型真好,父類可以呼叫子類得函式;相比C++就不行了,可能是C++的效率考慮吧 public void run() { if (target != null) { target.run(); } } /** * This method is called by the system to give a Thread * a chance to clean up before it actually exits. */ //退出執行緒 private void exit() { if (group != null) { //移出執行緒組,應該這個函式執行完,執行緒就終止了吧 group.remove(this); 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; }