1. 程式人生 > >JDK原始碼分析——Thread

JDK原始碼分析——Thread

說實話,這部分東西太多了,而且涉及到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;
    }