Java 之 線程狀態(tài)

Java 之 線程狀態(tài)和調(diào)度

線程的狀態(tài)

image

NEW

創(chuàng)建后尚未啟動(dòng)的線程處于這個(gè)狀態(tài)侨赡。

意思是這個(gè)線程沒(méi)有被start()啟動(dòng)于个,或者說(shuō)還根本不是一個(gè)真正意義上的線程换帜,從本質(zhì)上講這只是創(chuàng)建了一個(gè)Java外殼驮瞧,還沒(méi)有真正的線程來(lái)運(yùn)行粪摘。

不代表調(diào)用了start()叹括,狀態(tài)就立即改變算墨,中間還有一些步驟,如果在這個(gè)啟動(dòng)的過(guò)程中有另一個(gè)線程來(lái)獲取它的狀態(tài)汁雷,其實(shí)是不確定的净嘀,要看那些中間步驟是否已經(jīng)完成了。

RUNNABLE

RUNNABLE狀態(tài)包括了操作系統(tǒng)線程狀態(tài)中的Running和Ready摔竿,也就是處于此狀態(tài)的線程可能正在運(yùn)行面粮,也可能正在等待系統(tǒng)資源,如等待CPU為它分配時(shí)間片继低,如等待網(wǎng)絡(luò)IO讀取數(shù)據(jù)熬苍。

RUNNABLE狀態(tài)也可以理解為存活著正在嘗試征用CPU的線程(有可能這個(gè)瞬間并沒(méi)有占用CPU,但是它可能正在發(fā)送指令等待系統(tǒng)調(diào)度)袁翁。由于在真正的系統(tǒng)中柴底,并不是開(kāi)啟一個(gè)線程后,CPU就只為這一個(gè)線程服務(wù)粱胜,它必須使用許多調(diào)度算法來(lái)達(dá)到某種平衡柄驻,不過(guò)這個(gè)時(shí)候線程依然處于RUNNABLE狀態(tài)。

BLOCKED

BLOCKED稱為阻塞狀態(tài)焙压,或者說(shuō)線程已經(jīng)被掛起鸿脓,它“睡著”了,原因通常是它在等待一個(gè)“鎖”涯曲,當(dāng)嘗試進(jìn)入一個(gè)synchronized語(yǔ)句塊/方法時(shí)野哭,鎖已經(jīng)被其它線程占有,就會(huì)被阻塞幻件,直到另一個(gè)線程走完臨界區(qū)或發(fā)生了相應(yīng)鎖對(duì)象的wait()操作后拨黔,它才有機(jī)會(huì)去爭(zhēng)奪進(jìn)入臨界區(qū)的權(quán)利

在Java代碼中,需要考慮synchronized的粒度問(wèn)題绰沥,否則一個(gè)線程長(zhǎng)時(shí)間占用鎖篱蝇,其它爭(zhēng)搶鎖的線程會(huì)一直阻塞,直到擁有鎖的線程釋放鎖

處于BLOCKED狀態(tài)的線程徽曲,即使對(duì)其調(diào)用 thread.interrupt()也無(wú)法改變其阻塞狀態(tài)零截,因?yàn)閕nterrupt()方法只是設(shè)置線程的中斷狀態(tài),即做一個(gè)標(biāo)記秃臣,不能喚醒處于阻塞狀態(tài)的線程

注意:ReentrantLock.lock()操作后進(jìn)入的是WAITING狀態(tài)涧衙,其內(nèi)部調(diào)用的是LockSupport.park()方法

WAITING

處于這種狀態(tài)的線程不會(huì)被分配CPU執(zhí)行時(shí)間,它們要等待顯示的被其它線程喚醒。這種狀態(tài)通常是指一個(gè)線程擁有對(duì)象鎖后進(jìn)入到相應(yīng)的代碼區(qū)域后绍撞,調(diào)用相應(yīng)的“鎖對(duì)象”的wait()方法操作后產(chǎn)生的一種結(jié)果。變相的實(shí)現(xiàn)還有LockSupport.park()得院、Thread.join()等傻铣,它們也是在等待另一個(gè)事件的發(fā)生,也就是描述了等待的意思祥绞。

以下方法會(huì)讓線程陷入無(wú)限期等待狀態(tài):

(1)沒(méi)有設(shè)置timeout參數(shù)的Object.wait()

(2)沒(méi)有設(shè)置timeout參數(shù)的Thread.join()

(3)LockSupport.park()

注意:

LockSupport.park(Object blocker) 會(huì)掛起當(dāng)前線程非洲,參數(shù)blocker是用于設(shè)置當(dāng)前線程的“volatile Object parkBlocker 成員變量”

parkBlocker 是用于記錄線程是被誰(shuí)阻塞的,可以通過(guò)LockSupport.getBlocker()獲取到阻塞的對(duì)象蜕径,用于監(jiān)控和分析線程用的两踏。

“阻塞”與“等待”的區(qū)別:

(1)“阻塞”狀態(tài)是等待著獲取到一個(gè)排他鎖,進(jìn)入“阻塞”狀態(tài)都是被動(dòng)的兜喻,離開(kāi)“阻塞”狀態(tài)是因?yàn)槠渌€程釋放了鎖梦染,不阻塞了;

(2)“等待”狀態(tài)是在等待一段時(shí)間 或者 喚醒動(dòng)作的發(fā)生朴皆,進(jìn)入“等待”狀態(tài)是主動(dòng)的

如主動(dòng)調(diào)用Object.wait()帕识,如無(wú)法獲取到ReentraantLock,主動(dòng)調(diào)用LockSupport.park()遂铡,如主線程主動(dòng)調(diào)用 subThread.join()肮疗,讓主線程等待子線程執(zhí)行完畢再執(zhí)行

離開(kāi)“等待”狀態(tài)是因?yàn)槠渌€程發(fā)生了喚醒動(dòng)作或者到達(dá)了等待時(shí)間

TIMED_WAITING

處于這種狀態(tài)的線程也不會(huì)被分配CPU執(zhí)行時(shí)間,不過(guò)無(wú)需等待被其它線程顯示的喚醒扒接,在一定時(shí)間之后它們會(huì)由系統(tǒng)自動(dòng)的喚醒伪货。

以下方法會(huì)讓線程進(jìn)入TIMED_WAITING限期等待狀態(tài):

(1)Thread.sleep()方法

(2)設(shè)置了timeout參數(shù)的Object.wait()方法

(3)設(shè)置了timeout參數(shù)的Thread.join()方法

(4)LockSupport.parkNanos()方法

(5)LockSupport.parkUntil()方法

TERMINATED

已終止線程的線程狀態(tài),線程已經(jīng)結(jié)束執(zhí)行钾怔。換句話說(shuō)碱呼,run()方法走完了,線程就處于這種狀態(tài)蒂教。其實(shí)這只是Java語(yǔ)言級(jí)別的一種狀態(tài)巍举,在操作系統(tǒng)內(nèi)部可能已經(jīng)注銷了相應(yīng)的線程,或者將它復(fù)用給其他需要使用線程的請(qǐng)求凝垛,而在Java語(yǔ)言級(jí)別只是通過(guò)Java代碼看到的線程狀態(tài)而已懊悯。

四. Thread類中的方法

通過(guò)查看java.lang.Thread類的源碼可知:

image

Thread類實(shí)現(xiàn)了Runnable接口,在Thread類中梦皮,有一些比較關(guān)鍵的屬性炭分,比如name是表示Thread的名字,可以通過(guò)Thread類的構(gòu)造器中的參數(shù)來(lái)指定線程名字剑肯,priority表示線程的優(yōu)先級(jí)(最大值為10捧毛,最小值為1,默認(rèn)值為5),daemon表示線程是否是守護(hù)線程呀忧,target表示要執(zhí)行的任務(wù)师痕。

下面是Thread類中常用的方法:

以下是關(guān)系到線程運(yùn)行狀態(tài)的幾個(gè)方法:

1)start方法

start()用來(lái)啟動(dòng)一個(gè)線程,當(dāng)調(diào)用start方法后而账,系統(tǒng)才會(huì)開(kāi)啟一個(gè)新的線程來(lái)執(zhí)行用戶定義的子任務(wù)胰坟,在這個(gè)過(guò)程中,會(huì)為相應(yīng)的線程分配需要的資源泞辐。

2)run方法

run()方法是不需要用戶來(lái)調(diào)用的笔横,當(dāng)通過(guò)start方法啟動(dòng)一個(gè)線程之后,當(dāng)線程獲得了CPU執(zhí)行時(shí)間咐吼,便進(jìn)入run方法體去執(zhí)行具體的任務(wù)吹缔。注意,繼承Thread類必須重寫run方法锯茄,在run方法中定義具體要執(zhí)行的任務(wù)厢塘。

3)sleep方法

sleep方法有兩個(gè)重載版本:

//參數(shù)為毫秒
sleep(long millis) 
//第一參數(shù)為毫秒,第二個(gè)參數(shù)為納秒
sleep(long millis,int nanoseconds)

sleep相當(dāng)于讓線程睡眠肌幽,交出CPU俗冻,讓CPU去執(zhí)行其他的任務(wù)。

但是有一點(diǎn)要非常注意牍颈,sleep方法不會(huì)釋放鎖迄薄,也就是說(shuō)如果當(dāng)前線程持有對(duì)某個(gè)對(duì)象的鎖,則即使調(diào)用sleep方法煮岁,其他線程也無(wú)法訪問(wèn)這個(gè)對(duì)象讥蔽。看下面這個(gè)例子就清楚了:

public class Test {
     
    private int i = 10;
    private Object object = new Object();
     
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread1 = test.new MyThread();
        MyThread thread2 = test.new MyThread();
        thread1.start();
        thread2.start();
    } 
 
    class MyThread extends Thread{
        @Override
        public void run() {
            synchronized (object) {
                i++;
                System.out.println("i:"+i);
                try {
                    System.out.println("線程"+Thread.currentThread().getName()+"進(jìn)入睡眠狀態(tài)");
                    Thread.currentThread().sleep(10000);
                } catch (InterruptedException e) {
                    // TODO: handle exception
                }
                System.out.println("線程"+Thread.currentThread().getName()+"睡眠結(jié)束");
                i++;
                System.out.println("i:"+i);
            }
        }
    }
}

輸出結(jié)果:

image

從上面輸出結(jié)果可以看出画机,當(dāng)Thread-0進(jìn)入睡眠狀態(tài)之后冶伞,Thread-1并沒(méi)有去執(zhí)行具體的任務(wù)。只有當(dāng)Thread-0執(zhí)行完之后步氏,此時(shí)Thread-0釋放了對(duì)象鎖响禽,Thread-1才開(kāi)始執(zhí)行。

注意荚醒,如果調(diào)用了sleep方法芋类,必須捕獲InterruptedException異常或者將該異常向上層拋出界阁。當(dāng)線程睡眠時(shí)間滿后侯繁,不一定會(huì)立即得到執(zhí)行,因?yàn)榇藭r(shí)可能CPU正在執(zhí)行其他的任務(wù)泡躯。所以說(shuō)調(diào)用sleep方法相當(dāng)于讓線程進(jìn)入阻塞狀態(tài)贮竟。

4)yield方法

調(diào)用yield方法會(huì)讓當(dāng)前線程交出CPU權(quán)限丽焊,讓CPU去執(zhí)行其他的線程。它跟sleep方法類似咕别,同樣不會(huì)釋放鎖技健。但是yield不能控制具體的交出CPU的時(shí)間,另外惰拱,yield方法只能讓擁有相同優(yōu)先級(jí)的線程有獲取CPU執(zhí)行時(shí)間的機(jī)會(huì)凫乖。

注意,調(diào)用yield方法并不會(huì)讓線程進(jìn)入阻塞狀態(tài)弓颈,而是讓線程重回就緒狀態(tài),它只需要等待重新獲取CPU執(zhí)行時(shí)間删掀,這一點(diǎn)是和sleep方法不一樣的翔冀。

5)join方法

join方法有三個(gè)重載版本:

join()
join(long millis)     //參數(shù)為毫秒
join(long millis,int nanoseconds)    //第一參數(shù)為毫秒,第二個(gè)參數(shù)為納秒

假如在main線程中披泪,調(diào)用thread.join方法纤子,則main方法會(huì)等待thread線程執(zhí)行完畢或者等待一定的時(shí)間。如果調(diào)用的是無(wú)參join方法款票,則等待thread執(zhí)行完畢控硼,如果調(diào)用的是指定了時(shí)間參數(shù)的join方法,則等待一定的時(shí)間艾少。

看下面一個(gè)例子:

public class Test {
    public static void main(String[] args) throws IOException  {
        System.out.println("進(jìn)入線程"+Thread.currentThread().getName());
        Test test = new Test();
        MyThread thread1 = test.new MyThread();
        thread1.start();
        try {
            System.out.println("線程"+Thread.currentThread().getName()+"等待");
            thread1.join();
            System.out.println("線程"+Thread.currentThread().getName()+"繼續(xù)執(zhí)行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            System.out.println("進(jìn)入線程"+Thread.currentThread().getName());
            try {
                Thread.currentThread().sleep(5000);
            } catch (InterruptedException e) {
            }
            System.out.println("線程"+Thread.currentThread().getName()+"執(zhí)行完畢");
        }
    }
}

輸出結(jié)果:

image

可以看出卡乾,當(dāng)調(diào)用thread1.join()方法后,main線程會(huì)進(jìn)入等待缚够,然后等待thread1執(zhí)行完之后再繼續(xù)執(zhí)行幔妨。

實(shí)際上調(diào)用join方法是調(diào)用了Object的wait方法,這個(gè)可以通過(guò)查看源碼得知:

image

wait方法會(huì)讓線程進(jìn)入阻塞狀態(tài)谍椅,并且會(huì)釋放線程占有的鎖误堡,并交出CPU執(zhí)行權(quán)限。

由于wait方法會(huì)讓線程釋放對(duì)象鎖雏吭,所以join方法同樣會(huì)讓線程釋放對(duì)一個(gè)對(duì)象持有的鎖锁施。

6)interrupt方法

interrupt,顧名思義杖们,即中斷的意思悉抵。

單獨(dú)調(diào)用interrupt方法可以使得處于阻塞狀態(tài)的線程拋出一個(gè)異常,也就說(shuō)摘完,它可以用來(lái)中斷一個(gè)正處于阻塞狀態(tài)的線程基跑;另外,通過(guò)interrupt方法和isInterrupted()方法來(lái)停止正在運(yùn)行的線程描焰。

下面看一個(gè)例子:

public class Test {
     
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread = test.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {
        }
        thread.interrupt();
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            try {
                System.out.println("進(jìn)入睡眠狀態(tài)");
                Thread.currentThread().sleep(10000);
                System.out.println("睡眠完畢");
            } catch (InterruptedException e) {
                System.out.println("得到中斷異常");
            }
            System.out.println("run方法執(zhí)行完畢");
        }
    }
}

輸出結(jié)果:

image

從這里可以看出媳否,通過(guò)interrupt方法可以中斷處于阻塞狀態(tài)的線程栅螟。那么能不能中斷處于非阻塞狀態(tài)的線程呢?看下面這個(gè)例子:

public class Test {
     
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread = test.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {
             
        }
        thread.interrupt();
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            int i = 0;
            while(i<Integer.MAX_VALUE){
                System.out.println(i+" while循環(huán)");
                i++;
            }
        }
    }
}

運(yùn)行該程序會(huì)發(fā)現(xiàn)篱竭,while循環(huán)會(huì)一直運(yùn)行直到變量i的值超出Integer.MAX_VALUE力图。所以說(shuō)直接調(diào)用interrupt方法不能中斷正在運(yùn)行中的線程。

但是如果配合isInterrupted()能夠中斷正在運(yùn)行的線程掺逼,因?yàn)檎{(diào)用interrupt方法相當(dāng)于將中斷標(biāo)志位置為true吃媒,那么可以通過(guò)調(diào)用isInterrupted()判斷中斷標(biāo)志是否被置位來(lái)中斷線程的執(zhí)行。比如下面這段代碼:

public class Test {
     
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread = test.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {
             
        }
        thread.interrupt();
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            int i = 0;
            while(!isInterrupted() && i<Integer.MAX_VALUE){
                System.out.println(i+" while循環(huán)");
                i++;
            }
        }
    }
}

運(yùn)行會(huì)發(fā)現(xiàn)吕喘,打印若干個(gè)值之后赘那,while循環(huán)就停止打印了。

但是一般情況下不建議通過(guò)這種方式來(lái)中斷線程氯质,一般會(huì)在MyThread類中增加一個(gè)屬性 isStop來(lái)標(biāo)志是否結(jié)束while循環(huán)败玉,然后再在while循環(huán)中判斷isStop的值奋单。

class MyThread extends Thread{
    private volatile boolean isStop = false;
    @Override
    public void run() {
        int i = 0;
        while(!isStop){
            i++;
        }
    }

    public void setStop(boolean stop){
        this.isStop = stop;
    }
}

那么就可以在外面通過(guò)調(diào)用setStop方法來(lái)終止while循環(huán)砂轻。

7)stop方法

stop方法已經(jīng)是一個(gè)廢棄的方法守伸,它是一個(gè)不安全的方法。因?yàn)檎{(diào)用stop方法會(huì)直接終止run方法的調(diào)用辕漂,并且會(huì)拋出一個(gè)ThreadDeath錯(cuò)誤呢灶,如果線程持有某個(gè)對(duì)象鎖的話,會(huì)完全釋放鎖钉嘹,導(dǎo)致對(duì)象狀態(tài)不一致鸯乃。所以stop方法基本是不會(huì)被用到的。

8)destroy方法

destroy方法也是廢棄的方法跋涣§穑基本不會(huì)被使用到。

9)其他方法

以下是關(guān)系到線程屬性的幾個(gè)方法:

1)getId:用來(lái)得到線程ID

2)getName和setName:用來(lái)得到或者設(shè)置線程名稱仆潮。

3)getPriority和setPriority:用來(lái)獲取和設(shè)置線程優(yōu)先級(jí)宏蛉。

4)setDaemon和isDaemon:用來(lái)設(shè)置線程是否成為守護(hù)線程和判斷線程是否是守護(hù)線程。守護(hù)線程和用戶線程的區(qū)別在于:守護(hù)線程依賴于創(chuàng)建它的線程性置,而用戶線程則不依賴拾并。舉個(gè)簡(jiǎn)單的例子:如果在main線程中創(chuàng)建了一個(gè)守護(hù)線程,當(dāng)main方法運(yùn)行完畢之后鹏浅,守護(hù)線程也會(huì)隨著消亡嗅义。而用戶線程則不會(huì),用戶線程會(huì)一直運(yùn)行直到其運(yùn)行完畢隐砸。在JVM中之碗,像垃圾收集器線程就是守護(hù)線程。

5)currentThread:Thread類有一個(gè)比較常用的靜態(tài)方法currentThread()用來(lái)獲取當(dāng)前線程季希。

在上面已經(jīng)說(shuō)到了Thread類中的大部分方法褪那,那么Thread類中的方法調(diào)用到底會(huì)引起線程狀態(tài)發(fā)生怎樣的變化呢幽纷?下面一幅圖就是在上面的圖上進(jìn)行改進(jìn)而來(lái)的:

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市博敬,隨后出現(xiàn)的幾起案子友浸,更是在濱河造成了極大的恐慌,老刑警劉巖偏窝,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件收恢,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡祭往,警方通過(guò)查閱死者的電腦和手機(jī)伦意,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)硼补,“玉大人驮肉,你說(shuō)我怎么就攤上這事±ㄉ祝” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵曲掰,是天一觀的道長(zhǎng)疾捍。 經(jīng)常有香客問(wèn)我,道長(zhǎng)栏妖,這世上最難降的妖魔是什么乱豆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮吊趾,結(jié)果婚禮上宛裕,老公的妹妹穿的比我還像新娘。我一直安慰自己论泛,他們只是感情好揩尸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著屁奏,像睡著了一般岩榆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坟瓢,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天勇边,我揣著相機(jī)與錄音,去河邊找鬼折联。 笑死粒褒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诚镰。 我是一名探鬼主播奕坟,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼祥款,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了执赡?” 一聲冷哼從身側(cè)響起镰踏,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沙合,沒(méi)想到半個(gè)月后奠伪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡首懈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年绊率,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片究履。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡滤否,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出最仑,到底是詐尸還是另有隱情藐俺,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布泥彤,位于F島的核電站欲芹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏吟吝。R本人自食惡果不足惜菱父,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剑逃。 院中可真熱鬧浙宜,春花似錦、人聲如沸蛹磺。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)萤捆。三九已至亩钟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鳖轰,已是汗流浹背清酥。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蕴侣,地道東北人焰轻。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像昆雀,于是被迫代替她去往敵國(guó)和親辱志。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蝠筑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容