天天看點

Java中Thread源碼剖析Java中join和yield的作用

                                       本文來自 http://blog.csdn.net/liuxian13183/  ,引用必須注明出處!

關于線程,用很長時間了,主線程下的子線程去做一些事情,就是一個代理模式,主線程分代理權給子線程,子線程幫主線程完成一些任務。

線程的方法大部分都是使用Native使用,不允許應用層修改,是CPU排程的最基本單元。實作線程的方式有三種:使用核心線程、使用者線程和混合線程來實作,奉行先行發生的原則。

核心線程:每個生成的線程,都1:1配比一個核心線程來支援,即雙線程機制,消耗一個核心資源,類似手機中應用程序

使用者線程:普通線程,高速且低耗,建立、切換、排程等問題都需要自己處理

混合實作:降低被阻塞的風險,使用者線程與核心線程相當于M:N的關系

線程的排程方式主要有兩種:協同式和搶占式,前者簡單但不可控制,一個線程執行完通知另外一個;搶占式可以通過yield方法讓出執行時間,Java目前就采用這種,同時可以使用設定優先級的方式來提前線程執行順序,但有可能被“系統”關閉。

今天我們來看下線程的源碼,進行系統的學習。

1、首先線程有六種狀态

    public enum State {

        /**

         * The thread has been created, but has never been started.

         */

        NEW,

         * The thread may be run.

        RUNNABLE,

         * The thread is blocked and waiting for a lock.

        BLOCKED,

         * The thread is waiting.

        WAITING,

         * The thread is waiting for a specified amount of time.

        TIMED_WAITING,

         * The thread has been terminated.

        TERMINATED

    }

NEW:剛建立還沒啟動

RUNNABLE:可以執行 

BLOCKED:堵塞狀态,等待持有鎖

WAITING :處理等待狀态 

TIMED_WAITING:等待一些時間

TERMINATED:終止

    /**

     * The maximum priority value allowed for a thread.

     */

    public static final int MAX_PRIORITY = 10;

     * The minimum priority value allowed for a thread.

    public static final int MIN_PRIORITY = 1;

     * The normal (default) priority value assigned to threads.

    public static final int NORM_PRIORITY = 5;

2、分别是線程可設定的最大、最小和預設優先級,級别越高執行越靠前

     * Holds the thread's ID. We simply count upwards, so

     * each Thread has a unique ID.

    private long id;

3、每個線程都有一個獨一無二的ID

public Thread() {

        create(null, null, null, 0);

 private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {

        Thread currentThread = Thread.currentThread();

        if (group == null) {

            group = currentThread.getThreadGroup();

        }

        if (group.isDestroyed()) {

            throw new IllegalThreadStateException("Group already destroyed");

        this.group = group;

        synchronized (Thread.class) {

            id = ++Thread.count;

        if (threadName == null) {

            this.name = "Thread-" + id;

        } else {

            this.name = threadName;

        this.target = runnable;

        this.stackSize = stackSize;

        this.priority = currentThread.getPriority();

        this.contextClassLoader = currentThread.contextClassLoader;

        // Transfer over InheritableThreadLocals.

        if (currentThread.inheritableValues != null) {

            inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues);

        // add ourselves to our ThreadGroup of choice

        this.group.addThread(this);

4、初始化一個空的線程,獲得目前運作的線程群組,設定id,name,執行線程runnable,池大小stackSize,優先級,并加入到線程群組,這是一個無參的Thread,正常情況下應該有ThreadGroup、Runnable、threadName和stackSize這四個參數。一般threadName如果為空,則報出NullPointerException,stackSize預設為0。

     * Destroys the receiver without any monitor cleanup.

     *

     * @deprecated Not implemented.

    @Deprecated

    public void destroy() {

        throw new NoSuchMethodError("Thread.destroy()"); // TODO Externalize???

5、destroy方法在java7已經被抛棄。

    public void interrupt() {

        synchronized (interruptActions) {

            for (int i = interruptActions.size() - 1; i >= 0; i--) {

                interruptActions.get(i).run();

            }

        VMThread vmt = this.vmThread;

        if (vmt != null) {

            vmt.interrupt();

6、停止目前線程,如果線程處于wait、join、sleep狀态的線程,會報異常。

  public final boolean isAlive() {

        return (vmThread != null);

7、線程是否死掉,主要是判斷虛拟機線程有沒有死掉VMThread,當然獲得目前線程也是通過VMThread.currentThread(),以及接下下獲得目前線程處于六大狀态中的哪種。

    public State getState() {

        // TODO This is ugly and should be implemented better.

        // Make sure we have a valid reference to an object. If native code

        // deletes the reference we won't run into a null reference later.

        VMThread thread = vmThread;

        if (thread != null) {

            // If the Thread Object became invalid or was not yet started,

            // getStatus() will return -1.

            int state = thread.getStatus();

            if(state != -1) {

                return VMThread.STATE_MAP[state];

        return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW;

 public final void join() throws InterruptedException {

        VMThread t = vmThread;

        if (t == null) {

            return;

        synchronized (t) {

            while (isAlive()) {

                t.wait();

8、join堵塞目前線程,使其處于等待狀态,因為子線程執行的時間可能比主線程執行時間還長,是以join是主線程需要在它執行完後再銷毀。當然也可以加參數join(long millis, int nanos),使其等待N秒N毫秒,如果它已經處于join方法,則報InterruptedException 。

    public final void setDaemon(boolean isDaemon) {

        if (hasBeenStarted) {

            throw new IllegalThreadStateException("Thread already started."); // TODO Externalize?

        if (vmThread == null) {

            daemon = isDaemon;

9、設定為守護線程,必須的runnable執行前設定,會在有非守護線程運作的時候執行,無則程式退出。

    public final void setPriority(int priority) {

        if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {

            throw new IllegalArgumentException("Priority out of range"); // TODO Externalize?

        if (priority > group.getMaxPriority()) {

            priority = group.getMaxPriority();

        this.priority = priority;

            vmt.setPriority(priority);

10、優先級主要通過VMThread來設定的,注意最高設為10最低為1,否則報 IllegalArgumentException。

   public static void sleep(long millis, int nanos) throws InterruptedException {

        VMThread.sleep(millis, nanos);      

11、執行sleep,如果在sleep期間被interrupt,會報InterruptedException。

     * Starts the new Thread of execution. The <code>run()</code> method of

     * the receiver will be called by the receiver Thread itself (and not the

     * Thread calling <code>start()</code>).

     * @throws IllegalThreadStateException if the Thread has been started before

     * @see Thread#run

    public synchronized void start() {

        hasBeenStarted = true;

        VMThread.create(this, stackSize);

12、線程開始執行,如果start已經執行,則報IllegalThreadStateException

    public final synchronized void stop(Throwable throwable) {

        throw new UnsupportedOperationException();

13、stop方法棄用

public static void yield() {

        VMThread.yield();

14、給另一個準備運作的線程讓路,讓它先執行

關于join和yield的差別,更在上一節: 

Java中join和yield的作用