1. 程式人生 > >Java Thread 原始碼解析

Java Thread 原始碼解析

Thread 原始碼解析

執行緒的方法大部分都是使用Native使用,不允許應用層修改,是CPU排程的最基本單元。執行緒的資源開銷相對於程序的開銷是相對較少的,所以我們一般建立執行緒執行,而不是程序執行。

Thread 構造方法

/**
 * 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(); if (g == null) { g = parent.getThreadGroup(); } g.addUnstarted(); this.group = g; this.target = target; this.priority = parent.getPriority(); this
.daemon = parent.isDaemon(); setName(name); init2(parent); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; tid = nextThreadID(); } /** * Throws CloneNotSupportedException as a Thread can not be meaningfully * cloned. Construct a new Thread instead. * * @throws
CloneNotSupportedException * always */
@Override protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); } public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); } 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); } /** @hide */ // Android added : Private constructor - used by the runtime. Thread(ThreadGroup group, String name, int priority, boolean daemon) { this.group = group; this.group.addUnstarted(); // Must be tolerant of threads without a name. if (name == null) { name = "Thread-" + nextThreadNum(); } // NOTE: Resist the temptation to call setName() here. This constructor is only called // by the runtime to construct peers for threads that have attached via JNI and it's // undesirable to clobber their natively set name. this.name = name; this.priority = priority; this.daemon = daemon; init2(currentThread()); tid = nextThreadID(); } private void init2(Thread parent) { this.contextClassLoader = parent.getContextClassLoader(); this.inheritedAccessControlContext = AccessController.getContext(); if (parent.inheritableThreadLocals != null) { this.inheritableThreadLocals = ThreadLocal.createInheritedMap( parent.inheritableThreadLocals); } } 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); }

Thread 中構造方法好好多種,如果在構造方法中沒有傳入執行緒name,那麼Thread類中是會預設的為我們規定執行緒名字,即呼叫的是Thread- nextThreadNum(),對執行緒進行編號。 這個方法是同步的,保證了在執行的時候不會進行非同步操作,避免了產生有相同的線ID的出現。在構造方法中都執行了init()方法, init 方法是私有的,會判斷ThreadGroup 是否為空。

Thread的是實現了Runnable介面的,run 方法應該是怎麼執行的?

@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

run 方法中的target 變數就是我們在初始化的時候傳入的變數,如果子類複寫了run 方法,就不會呼叫target.run()

Thread 中重要的方法:

start() 方法

/**
 * 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)
        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);

    started = false;
    try {
        nativeCreate(this, stackSize, daemon);
        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 */
        }
    }
}

start( )方法是同步的,並且是啟動這個執行緒進行執行,Java虛擬機器將會呼叫這個執行緒的run方法,這樣產生的結果是,兩個執行緒執行著,其中一個是呼叫start()方法的執行緒執行,另一個執行緒是執行run方法的執行緒。在start()方法中,首先進行的執行緒狀態的判斷,如果是一個JVM新啟動的執行緒,那麼threadStatus 的狀態是為0的,如果執行緒不為0 將報出異常, 然後將執行緒新增到group中, group.add(this)方法中執行的結果是,通知group, 這個執行緒要執行了,所以可以新增進group中,然後呼叫本地方法nativeCreate(this, stackSize, daemon);

sleep() 方法

/**
 * Causes the currently executing thread to sleep (temporarily 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
 *         {@code 0-999999} additional nanoseconds to sleep
 *
 * @throws  IllegalArgumentException
 *          if the value of {@code millis} is negative, or the value of
 *          {@code nanos} is not in the range {@code 0-999999}
 *
 * @throws  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.
 */
public static void sleep(long millis, int nanos)
throws InterruptedException {
    if (millis < 0) {
        throw new IllegalArgumentException("millis < 0: " + millis);
    }
    if (nanos < 0) {
        throw new IllegalArgumentException("nanos < 0: " + nanos);
    }
    if (nanos > 999999) {
        throw new IllegalArgumentException("nanos > 999999: " + nanos);
    }

    // The JLS 3rd edition, section 17.9 says: "...sleep for zero
    // time...need not have observable effects."
    if (millis == 0 && nanos == 0) {
        // ...but we still have to handle being interrupted.
        if (Thread.interrupted()) {
          throw new InterruptedException();
        }
        return;
    }

    long start = System.nanoTime();
    long duration = (millis * NANOS_PER_MILLI) + nanos;

    Object lock = currentThread().lock;

    // Wait may return early, so loop until sleep duration passes.
    synchronized (lock) {
        while (true) {
            sleep(lock, millis, nanos);

            long now = System.nanoTime();
            long elapsed = now - start;

            if (elapsed >= duration) {
                break;
            }

            duration -= elapsed;
            start = now;
            millis = duration / NANOS_PER_MILLI;
            nanos = (int) (duration % NANOS_PER_MILLI);
        }
    }
}

sleep()方法在使用執行緒的時候,用的是比較多的。 這個方法的作用使得當前執行緒休眠一定的時間,但是這個期間是不釋放持有的鎖的。這個方法裡面首先進行的是休眠時間的判斷,然後又是呼叫本地方法。

join()方法

/**
 * Waits at most {@code millis} milliseconds for this thread to
 * die. A timeout of {@code 0} means to wait forever.
 *
 * <p> This implementation uses a loop of {@code this.wait} calls
 * conditioned on {@code this.isAlive}. As a thread terminates the
 * {@code this.notifyAll} method is invoked. It is recommended that
 * applications not use {@code wait}, {@code notify}, or
 * {@code notifyAll} on {@code Thread} instances.
 *
 * @param  millis
 *         the time to wait in milliseconds
 *
 * @throws  IllegalArgumentException
 *          if the value of {@code millis} is negative
 *
 * @throws  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.
 */
public final void join(long millis) throws InterruptedException {
    synchronized(lock) {
    long base = System.currentTimeMillis();
    long now = 0;

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) {
        while (isAlive()) {
            lock.wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            lock.wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
    }
}

join方法是等待該執行緒執行,直到超時或者終止,可以作為執行緒通訊的一種方式,A執行緒呼叫B執行緒的join(阻塞),等待B完成後再往下執行

interrupt()方法

public void interrupt() {
    if (this != Thread.currentThread())
        checkAccess();

    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            nativeInterrupt();
            b.interrupt(this);
            return;
        }
    }
    nativeInterrupt();
}

interrupt()方法是中斷當前的執行緒,一般來說,阻塞函式:如Thread.sleep、Thread.join、Object.wait等在檢查到執行緒的中斷狀態的時候,會丟擲InteruptedExeption, 同時會清除執行緒的中斷狀態。

執行緒狀態

/**
 * A thread state.  A thread can be in one of the following states:
 * <ul>
 * <li>{@link #NEW}<br>
 *     A thread that has not yet started is in this state.
 *     </li>
 * <li>{@link #RUNNABLE}<br>
 *     A thread executing in the Java virtual machine is in this state.
 *     </li>
 * <li>{@link #BLOCKED}<br>
 *     A thread that is blocked waiting for a monitor lock
 *     is in this state.
 *     </li>
 * <li>{@link #WAITING}<br>
 *     A thread that is waiting indefinitely for another thread to
 *     perform a particular action is in this state.
 *     </li>
 * <li>{@link #TIMED_WAITING}<br>
 *     A thread that is waiting for another thread to perform an action
 *     for up to a specified waiting time is in this state.
 *     </li>
 * <li>{@link #TERMINATED}<br>
 *     A thread that has exited is in this state.
 *     </li>
 * </ul>
 *
 * <p>
 * A thread can be in only one state at a given point in time.
 * These states are virtual machine states which do not reflect
 * any operating system thread states.
 *
 * @since   1.5
 * @see #getState
 */
public enum State {
    /**
     * Thread state for a thread which has not yet started.
     */
    NEW,

    /**
     * Thread state for a runnable thread.  A thread in the runnable
     * state is executing in the Java virtual machine but it may
     * be waiting for other resources from the operating system
     * such as processor.
     */
    RUNNABLE,

    /**
     * Thread state for a thread blocked waiting for a monitor lock.
     * A thread in the blocked state is waiting for a monitor lock
     * to enter a synchronized block/method or
     * reenter a synchronized block/method after calling
     * {@link Object#wait() Object.wait}.
     */
    BLOCKED,

    /**
     * Thread state for a waiting thread.
     * A thread is in the waiting state due to calling one of the
     * following methods:
     * <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>A thread in the waiting state is waiting for another thread to
     * perform a particular action.
     *
     * For example, a thread that has called <tt>Object.wait()</tt>
     * on an object is waiting for another thread to call
     * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
     * that object. A thread that has called <tt>Thread.join()</tt>
     * is waiting for a specified thread to terminate.
     */
    WAITING,

    /**
     * Thread state for a waiting thread with a specified waiting time.
     * A thread is in the timed waiting state due to calling one of
     * the following methods with a specified positive waiting time:
     * <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,

    /**
     * Thread state for a terminated thread.
     * The thread has completed execution.
     */
    TERMINATED;
}

1、NEW

新建立的執行緒,還沒有呼叫start()方法

2、 RUNNABLE
可以執行,需要再等到其他資源(如CPU)就緒才能執行
3、 BLOCKED
執行緒呼叫wait()後等待內建鎖進入同步方法或塊中

4、WAITING
在呼叫無參的wait(),Thread.join()

5、TIMED_WAITING
呼叫Thread.sleep(), 有時間引數的wait(), 有時間引數的Thread.join()
6、TERMINATED
執行完畢的執行緒狀態