91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

并發編程專題(三)-線程的狀態

發布時間:2020-05-03 10:04:44 來源:網絡 閱讀:307 作者:BRUCELIU9527 欄目:編程語言
1.線程狀態

Java中,線程的狀態使用一個枚舉類型來描述的。這個枚舉一共有6個值: NEW(新建)RUNNABLE(運行)BLOCKED(鎖池)TIMED_WAITING(定時等待)WAITING(等待)TERMINATED(終止、結束)
但是大多數人的理解和上面的這六種還是有些差別,通常會加上阻塞狀態,可運行狀態,掛起狀態。
在API中 java.lang.Thread.State 這個枚舉中給出了六種線程狀態,
這是Thread類描述線程狀態的枚舉類的源代碼:

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;
    }
2.大多數人對線程狀態以及狀態轉換的理解

線程從創建、運行到結束總是處于下面五個狀態之一:新建狀態、就緒狀態、運行狀態、阻塞狀態及死亡狀態。
線程狀態轉換圖:
并發編程專題(三)-線程的狀態

2.1 新建狀態

當用new操作符創建一個線程時, 例如new Thread(r),線程還沒有開始運行,此時線程處在新建狀態。 當一個線程處于新生狀態時,程序還沒有開始運行線程中的代碼。

2.2 就緒狀態

一個新創建的線程并不自動開始運行,要執行線程,必須調用線程的start()方法。當線程對象調用start()方法即啟動了線程,start()方法創建線程運行的系統資源,并調度線程運行run()方法。當start()方法返回后,線程就處于就緒狀態。

處于就緒狀態的線程并不一定立即運行run()方法,線程還必須同其他線程競爭CPU時間,只有獲得CPU時間才可以運行線程。因為在單CPU的計算機系統中,不可能同時運行多個線程,一個時刻僅有一個線程處于運行狀態。因此此時可能有多個線程處于就緒狀態。對多個處于就緒狀態的線程是由

Java運行時系統的線程調度程序(thread scheduler)來調度的。

2.3 運行狀態

當線程獲得CPU時間后,它才進入運行狀態,真正開始執行run()方法.

2.4 阻塞狀態

線程運行過程中,可能由于各種原因進入阻塞狀態:

  1. 線程通過調用sleep方法進入睡眠狀態;
    2.線程調用一個在I/O上被阻塞的操作,即該操作在輸入輸出操作完成之前不會返回到它的調用者;
    3.線程試圖得到一個鎖,而該鎖正被其他線程持有;
    4.線程在等待某個觸發條件;
2.5 死亡狀態

有兩個原因會導致線程死亡:
1.run方法正常退出而自然死亡,

  1. 一個未捕獲的異常終止了run方法而使線程猝死。
    為了確定線程在當前是否存活著(就是要么是可運行的,要么是被阻塞了),需要使用isAlive方法。如果是可運行或被阻塞,這個方法返回true; 如果線程仍舊是new狀態且不是可運行的, 或者線程死亡了,則返回false.
    3.對線程狀態以及狀態轉換的另外理解

    據官方源碼,一個線程有六個狀態,沒有阻塞狀態,沒有可運行,沒有掛起狀態。這里先列出各個線程狀態發生的條件,下面將會對每種狀態進行詳細解析:
    并發編程專題(三)-線程的狀態

線程狀態 導致狀態發生修改的條件
NEW(新建) 線程剛被創建,但是并未啟動。還沒調用start()方法。
Runnable(可運行) 線程可以在java虛擬機中運行的狀態,可能正在運行自己代碼,也可能沒有,這取決于操作系統處理器。
Blocked(鎖阻塞) 當一個線程試圖獲取一個對象鎖,而該對象鎖被其他的線程持有,則該線程進入Blocked狀態;當該線程持有鎖時,該線程將變成Runnable狀態。
Waiting(無限 等待) 一個線程在等待另一個線程執行一個(喚醒)動作時,該線程進入Waiting狀態。進入這個狀態后是不能自動喚醒的,必須等待另一個線程調用notify或者notifyAll方法才能夠喚醒。
Timed Waiting(計時等待) 同waiting狀態,有幾個方法有超時參數,調用他們將進入TimedWaiting狀態。這一狀態將一直保持到超時期滿或者接收到喚醒通知。帶有超時參數的常用方法有Thread.sleep、Object.wait。
Teminated(被 終止) 因為run方法正常退出而死亡,或者因為沒有捕獲的異常終止了run方法而死亡。

我們不需要去研究這幾種狀態的實現原理,我們只需知道在做線程操作中存在這樣的狀態。那我們怎么去理解這幾個狀態呢,新建與被終止還是很容易理解的,我們就研究一下線程從Runnable(可運行)狀態與非運行狀態之間 的轉換問題。

3.1 TimedWaiting(計時等待)

當線程調用sleep()方法或當前線程中有其他線程調用了帶時間參數的join()方法的時候進入了定時等待狀態(TIMED_WAITING)。

代碼示例:

/**
 * @author bruceliu
 * @create 2019-06-01 22:35
 * @description TimedWaiting(計時等待)
 */
public class Test1 {
    public static void main(String[] args) {
        Thread1 t1 = new Thread1();
        Thread2 t2 = new Thread2();
        t1.setThread2(t2);

        t1.start();
        t2.start();
    }
}

//Thread1負責打印兩個線程的狀態。
class Thread1 extends Thread {
    private Thread2 t2;

    public void setThread2(Thread2 t2) {
        this.t2 = t2;
    }

    @Override
    public void run() {
        System.out.println("進入t1線程");
        for (int i = 0; i < 5; i++) {
            try {
                System.out.println("t1 的狀態: " + getState());
                System.out.println("t2 的狀態: " + t2.getState());
                System.out.println();

                //為了減少打印次數,所以t1每打印一次睡1秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {

            }
        }
    }
}

class Thread2 extends Thread {
    @Override
    public void run() {
        System.out.println("進入t2線程,馬上進入睡眠");
        try {
            //睡眠5秒鐘。
            sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("t2睡眠結束");
    }
}

通過案例可以發現,sleep方法的使用還是很簡單的。我們需要記住下面幾點:

  1. 進入 TIMED_WAITING 狀態的一種常見情形是調用的 sleep 方法,單獨的線程也可以調用,不一定非要有協作關系。
  2. 為了讓其他線程有機會執行,可以將Thread.sleep()的調用放線程run()之內。這樣才能保證該線程執行過程中會睡眠
  3. sleep與鎖無關,線程睡眠到期自動蘇醒,并返回到Runnable(可運行)狀態。

    sleep()中指定的時間是線程不會運行的最短時間。因此,sleep()方法不能保證該線程睡眠到期后就開始立刻執行。

Timed Waiting 線程狀態圖:
并發編程專題(三)-線程的狀態

3.2 BLOCKED(鎖阻塞)

Blocked狀態在API中的介紹為:一個正在阻塞等待一個監視器鎖(鎖對象)的線程處于這一狀態。
如果我們已經學完同步機制,那么這個狀態是非常好理解的了。比如,線程A與線程B代碼中使用同一鎖,如果線程A獲取到鎖,線程A進入到Runnable狀態,那么線程B就進入到Blocked鎖阻塞狀態。
這是由Runnable狀態進入Blocked狀態。除此Waiting以及Time Waiting狀態也會在某種情況下進入阻塞狀態,而這部分內容作為擴充知識點帶領大家了解一下。

Blocked 線程狀態圖:
并發編程專題(三)-線程的狀態

3.3 Waiting(無限等待)

Wating狀態在API中介紹為:一個正在無限期等待另一個線程執行一個特別的(喚醒)動作的線程處于這一狀態。那么我們之前遇到過這種狀態嗎?答案是并沒有,但并不妨礙我們進行一個簡單深入的了解。我們通過一段代碼來學習一下:

package com.bruceliu.demo7;

/**
 * @author bruceliu
 * @create 2019-05-30 16:59
 * @description
 */
public class WaitingTest {

    public static Object obj = new Object();

    public static void main(String[] args) {

        // 演示waiting
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (obj) {
                        try {
                            System.out.println(Thread.currentThread().getName() + "=== 從waiting狀態醒來,獲取到鎖對象,繼續執行了");
                            obj.wait(); //無限等待
                            //obj.wait(5000); //計時等待, 5秒 時間到,自動醒來
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "=== 從waiting狀 態醒來,獲取到鎖對象,繼續執行了");
                    }
                }
            }
        }, "等待線程").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) { //每隔3秒 喚醒一次
                    try {
                        System.out.println(Thread.currentThread().getName() + "‐‐‐‐‐ 等待3秒鐘");
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (obj) {
                        System.out.println(Thread.currentThread().getName() + "‐‐‐‐‐ 獲取到鎖對 象,調用notify方法,釋放鎖對象");
                        obj.notify();
                    }
                }
            }
        }, "喚醒線程").start();
    }
}

通過上述案例我們會發現,一個調用了某個對象的 Object.wait 方法的線程會等待另一個線程調用此對象的Object.notify()方法 或 Object.notifyAll()方法。其實waiting狀態并不是一個線程的操作,它體現的是多個線程間的通信,可以理解為多個線程之間的協作關系,多個線程會爭取鎖,同時相互之間又存在協作關系。就好比在公司里你和你的同事們,你們可能存在晉升時的競爭,但更多時候你們更多是一起合作以完成某些任務。當多個線程協作時,比如A,B線程,如果A線程在Runnable(可運行)狀態中調用了wait()方法那么A線程就進入了Waiting(無限等待)狀態,同時失去了同步鎖。假如這個時候B線程獲取到了同步鎖,在運行狀態中調用了notify()方法,那么就會將無限等待的A線程喚醒。注意是喚醒,如果獲取到鎖對象,那么A線程喚醒后就進入Runnable(可運行)狀態;如果沒有獲取鎖對象,那么就進入到Blocked(鎖阻塞狀態)。

Waiting 線程狀態圖:
并發編程專題(三)-線程的狀態

3.4 小結

到此為止我們已經對線程狀態有了基本的認識,想要有更多的了解,詳情可以見下圖:

并發編程專題(三)-線程的狀態

我們在翻閱API的時候會發現Timed Waiting(計時等待) 與 Waiting(無限等待) 狀態聯系還是很緊密的,比如Waiting(無限等待) 狀態中wait方法是空參的,而timed waiting(計時等待) 中wait方法是帶參的。這種帶參的方法,其實是一種倒計時操作,相當于我們生活中的小鬧鐘,我們設定好時間,到時通知,可是如果提前得到(喚醒)通知,那么設定好時間在通知也就顯得多此一舉了,那么這種設計方案其實是一舉兩得。如果沒有得到(喚醒)通知,那么線程就處于Timed Waiting狀態,直到倒計時完畢自動醒來;如果在倒計時期間得到(喚醒)通知,那么線程從Timed Waiting狀態立刻喚醒。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

双鸭山市| 靖边县| 深水埗区| 太白县| 隆林| 灵丘县| 河西区| 靖边县| 惠东县| 潢川县| 辽阳市| 钦州市| 呼玛县| 基隆市| 平湖市| 哈巴河县| 江西省| 沙雅县| 锡林浩特市| 江津市| 峨山| 阿尔山市| 夏津县| 晋江市| 青川县| 通渭县| 民丰县| 鹤庆县| 托克托县| 辽阳县| 馆陶县| 永昌县| 桦甸市| 承德县| 兴业县| 通州市| 罗甸县| 福清市| 留坝县| 岱山县| 墨竹工卡县|