欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

并發(fā)編程專題(三)-線程的狀態(tài)

1.線程狀態(tài)

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

為五通橋等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及五通橋網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站制作、網(wǎng)站建設(shè)、五通橋網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!

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.大多數(shù)人對線程狀態(tài)以及狀態(tài)轉(zhuǎn)換的理解

線程從創(chuàng)建、運(yùn)行到結(jié)束總是處于下面五個(gè)狀態(tài)之一:新建狀態(tài)、就緒狀態(tài)、運(yùn)行狀態(tài)、阻塞狀態(tài)及死亡狀態(tài)。
線程狀態(tài)轉(zhuǎn)換圖:
并發(fā)編程專題(三)-線程的狀態(tài)

2.1 新建狀態(tài)

當(dāng)用new操作符創(chuàng)建一個(gè)線程時(shí), 例如new Thread(r),線程還沒有開始運(yùn)行,此時(shí)線程處在新建狀態(tài)。 當(dāng)一個(gè)線程處于新生狀態(tài)時(shí),程序還沒有開始運(yùn)行線程中的代碼。

2.2 就緒狀態(tài)

一個(gè)新創(chuàng)建的線程并不自動(dòng)開始運(yùn)行,要執(zhí)行線程,必須調(diào)用線程的start()方法。當(dāng)線程對象調(diào)用start()方法即啟動(dòng)了線程,start()方法創(chuàng)建線程運(yùn)行的系統(tǒng)資源,并調(diào)度線程運(yùn)行run()方法。當(dāng)start()方法返回后,線程就處于就緒狀態(tài)。

處于就緒狀態(tài)的線程并不一定立即運(yùn)行run()方法,線程還必須同其他線程競爭CPU時(shí)間,只有獲得CPU時(shí)間才可以運(yùn)行線程。因?yàn)樵趩蜟PU的計(jì)算機(jī)系統(tǒng)中,不可能同時(shí)運(yùn)行多個(gè)線程,一個(gè)時(shí)刻僅有一個(gè)線程處于運(yùn)行狀態(tài)。因此此時(shí)可能有多個(gè)線程處于就緒狀態(tài)。對多個(gè)處于就緒狀態(tài)的線程是由

Java運(yùn)行時(shí)系統(tǒng)的線程調(diào)度程序(thread scheduler)來調(diào)度的。

2.3 運(yùn)行狀態(tài)

當(dāng)線程獲得CPU時(shí)間后,它才進(jìn)入運(yùn)行狀態(tài),真正開始執(zhí)行run()方法.

2.4 阻塞狀態(tài)

線程運(yùn)行過程中,可能由于各種原因進(jìn)入阻塞狀態(tài):

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

有兩個(gè)原因會(huì)導(dǎo)致線程死亡:
1.run方法正常退出而自然死亡,

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

    據(jù)官方源碼,一個(gè)線程有六個(gè)狀態(tài),沒有阻塞狀態(tài),沒有可運(yùn)行,沒有掛起狀態(tài)。這里先列出各個(gè)線程狀態(tài)發(fā)生的條件,下面將會(huì)對每種狀態(tài)進(jìn)行詳細(xì)解析:
    并發(fā)編程專題(三)-線程的狀態(tài)

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

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

3.1 TimedWaiting(計(jì)時(shí)等待)

當(dāng)線程調(diào)用sleep()方法或當(dāng)前線程中有其他線程調(diào)用了帶時(shí)間參數(shù)的join()方法的時(shí)候進(jìn)入了定時(shí)等待狀態(tài)(TIMED_WAITING)。

代碼示例:

/**
 * @author bruceliu
 * @create 2019-06-01 22:35
 * @description TimedWaiting(計(jì)時(shí)等待)
 */
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負(fù)責(zé)打印兩個(gè)線程的狀態(tài)。
class Thread1 extends Thread {
    private Thread2 t2;

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

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

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

            }
        }
    }
}

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

通過案例可以發(fā)現(xiàn),sleep方法的使用還是很簡單的。我們需要記住下面幾點(diǎn):

  1. 進(jìn)入 TIMED_WAITING 狀態(tài)的一種常見情形是調(diào)用的 sleep 方法,單獨(dú)的線程也可以調(diào)用,不一定非要有協(xié)作關(guān)系。
  2. 為了讓其他線程有機(jī)會(huì)執(zhí)行,可以將Thread.sleep()的調(diào)用放線程run()之內(nèi)。這樣才能保證該線程執(zhí)行過程中會(huì)睡眠
  3. sleep與鎖無關(guān),線程睡眠到期自動(dòng)蘇醒,并返回到Runnable(可運(yùn)行)狀態(tài)。

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

Timed Waiting 線程狀態(tài)圖:
并發(fā)編程專題(三)-線程的狀態(tài)

3.2 BLOCKED(鎖阻塞)

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

Blocked 線程狀態(tài)圖:
并發(fā)編程專題(三)-線程的狀態(tài)

3.3 Waiting(無限等待)

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

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狀態(tài)醒來,獲取到鎖對象,繼續(xù)執(zhí)行了");
                            obj.wait(); //無限等待
                            //obj.wait(5000); //計(jì)時(shí)等待, 5秒 時(shí)間到,自動(dòng)醒來
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "=== 從waiting狀 態(tài)醒來,獲取到鎖對象,繼續(xù)執(zhí)行了");
                    }
                }
            }
        }, "等待線程").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() + "‐‐‐‐‐ 獲取到鎖對 象,調(diào)用notify方法,釋放鎖對象");
                        obj.notify();
                    }
                }
            }
        }, "喚醒線程").start();
    }
}

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

Waiting 線程狀態(tài)圖:
并發(fā)編程專題(三)-線程的狀態(tài)

3.4 小結(jié)

到此為止我們已經(jīng)對線程狀態(tài)有了基本的認(rèn)識,想要有更多的了解,詳情可以見下圖:

并發(fā)編程專題(三)-線程的狀態(tài)

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

分享文章:并發(fā)編程專題(三)-線程的狀態(tài)
本文路徑:http://chinadenli.net/article12/jpssgc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計(jì)公司面包屑導(dǎo)航品牌網(wǎng)站設(shè)計(jì)小程序開發(fā)網(wǎng)站設(shè)計(jì)網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名