線程的狀態(tài)轉(zhuǎn)換以及基本操作

原創(chuàng)文章&經(jīng)驗(yàn)總結(jié)&從校招到A廠一路陽(yáng)光一路滄桑

詳情請(qǐng)戳www.codercc.com

image
在上一篇文章中http://www.reibang.com/p/959cf355b574談到了為什么花功夫去學(xué)習(xí)并發(fā)編程的技術(shù),也就是說我們必須了解到并發(fā)編程的優(yōu)缺點(diǎn)神僵,我們?cè)谑裁辞闆r下可以去考慮開啟多個(gè)線程去實(shí)現(xiàn)我們的業(yè)務(wù)践宴,當(dāng)然使用多線程我們應(yīng)該著重注意一些什么恨溜,在上一篇文章中會(huì)有一些討論。那么听绳,說了這么多失暴,無(wú)論是針對(duì)面試還是實(shí)際工作中作為一名軟件開發(fā)人員都應(yīng)該具備這樣的技能军浆。萬(wàn)事開頭難棕洋,接下來就應(yīng)該了解如何新建一個(gè)線程?線程狀態(tài)是怎樣轉(zhuǎn)換的乒融?關(guān)于線程狀態(tài)的操作是怎樣的掰盘?這篇文章就主要圍繞這三個(gè)方面來聊一聊摄悯。

1. 新建線程

一個(gè)java程序從main()方法開始執(zhí)行,然后按照既定的代碼邏輯執(zhí)行愧捕,看似沒有其他線程參與奢驯,但實(shí)際上java程序天生就是一個(gè)多線程程序,包含了:(1)分發(fā)處理發(fā)送給給JVM信號(hào)的線程次绘;(2)調(diào)用對(duì)象的finalize方法的線程瘪阁;(3)清除Reference的線程;(4)main線程邮偎,用戶程序的入口管跺。那么,如何在用戶程序中新建一個(gè)線程了钢猛,只要有三種方式:

  1. 通過繼承Thread類伙菜,重寫run方法轩缤;

  2. 通過實(shí)現(xiàn)runable接口命迈;

  3. 通過實(shí)現(xiàn)callable接口這三種方式,下面看具體demo火的。

     public class CreateThreadDemo {
     
         public static void main(String[] args) {
             //1.繼承Thread
             Thread thread = new Thread() {
                 @Override
                 public void run() {
                     System.out.println("繼承Thread");
                     super.run();
                 }
             };
             thread.start();
             //2.實(shí)現(xiàn)runable接口
             Thread thread1 = new Thread(new Runnable() {
                 @Override
                 public void run() {
                     System.out.println("實(shí)現(xiàn)runable接口");
                 }
             });
             thread1.start();
             //3.實(shí)現(xiàn)callable接口
             ExecutorService service = Executors.newSingleThreadExecutor();
             Future<String> future = service.submit(new Callable() {
                 @Override
                 public String call() throws Exception {
                     return "通過實(shí)現(xiàn)Callable接口";
                 }
             });
             try {
                 String result = future.get();
                 System.out.println(result);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             } catch (ExecutionException e) {
                 e.printStackTrace();
             }
         }
     
     }
    

三種新建線程的方式具體看以上注釋壶愤,需要主要的是:

  • 由于java不能多繼承可以實(shí)現(xiàn)多個(gè)接口,因此馏鹤,在創(chuàng)建線程的時(shí)候盡量多考慮采用實(shí)現(xiàn)接口的形式征椒;
  • 實(shí)現(xiàn)callable接口,提交給ExecutorService返回的是異步執(zhí)行的結(jié)果湃累,另外勃救,通常也可以利用FutureTask(Callable<V> callable)將callable進(jìn)行包裝然后FeatureTask提交給ExecutorsService。如圖治力,
FutureTask接口實(shí)現(xiàn)關(guān)系

另外由于FeatureTask也實(shí)現(xiàn)了Runable接口也可以利用上面第二種方式(實(shí)現(xiàn)Runable接口)來新建線程蒙秒;

  • 可以通過Executors將Runable轉(zhuǎn)換成Callable,具體方法是:Callable<T> callable(Runnable task, T result)宵统, Callable<Object> callable(Runnable task)晕讲。

2. 線程狀態(tài)轉(zhuǎn)換

線程狀態(tài)轉(zhuǎn)換圖

此圖來源于《JAVA并發(fā)編程的藝術(shù)》一書中,線程是會(huì)在不同的狀態(tài)間進(jìn)行轉(zhuǎn)換的马澈,java線程線程轉(zhuǎn)換圖如上圖所示瓢省。線程創(chuàng)建之后調(diào)用start()方法開始運(yùn)行,當(dāng)調(diào)用wait(),join(),LockSupport.lock()方法線程會(huì)進(jìn)入到WAITING狀態(tài)痊班,而同樣的wait(long timeout)勤婚,sleep(long),join(long),LockSupport.parkNanos(),LockSupport.parkUtil()增加了超時(shí)等待的功能,也就是調(diào)用這些方法后線程會(huì)進(jìn)入TIMED_WAITING狀態(tài)涤伐,當(dāng)超時(shí)等待時(shí)間到達(dá)后馒胆,線程會(huì)切換到Runable的狀態(tài)荆永,另外當(dāng)WAITING和TIMED _WAITING狀態(tài)時(shí)可以通過Object.notify(),Object.notifyAll()方法使線程轉(zhuǎn)換到Runable狀態(tài)。當(dāng)線程出現(xiàn)資源競(jìng)爭(zhēng)時(shí)国章,即等待獲取鎖的時(shí)候具钥,線程會(huì)進(jìn)入到BLOCKED阻塞狀態(tài),當(dāng)線程獲取鎖時(shí)液兽,線程進(jìn)入到Runable狀態(tài)骂删。線程運(yùn)行結(jié)束后,線程進(jìn)入到TERMINATED狀態(tài)四啰,狀態(tài)轉(zhuǎn)換可以說是線程的生命周期宁玫。另外需要注意的是:

  • 當(dāng)線程進(jìn)入到synchronized方法或者synchronized代碼塊時(shí),線程切換到的是BLOCKED狀態(tài)柑晒,而使用java.util.concurrent.locks下lock進(jìn)行加鎖的時(shí)候線程切換的是WAITING或者TIMED_WAITING狀態(tài)欧瘪,因?yàn)閘ock會(huì)調(diào)用LockSupport的方法。

用一個(gè)表格將上面六種狀態(tài)進(jìn)行一個(gè)總結(jié)歸納匙赞。

JAVA線程的狀態(tài)

3. 線程狀態(tài)的基本操作

除了新建一個(gè)線程外佛掖,線程在生命周期內(nèi)還有需要基本操作,而這些操作會(huì)成為線程間一種通信方式涌庭,比如使用中斷(interrupted)方式通知實(shí)現(xiàn)線程間的交互等等芥被,下面就將具體說說這些操作。

3.1. interrupted

中斷可以理解為線程的一個(gè)標(biāo)志位坐榆,它表示了一個(gè)運(yùn)行中的線程是否被其他線程進(jìn)行了中斷操作拴魄。中斷好比其他線程對(duì)該線程打了一個(gè)招呼。其他線程可以調(diào)用該線程的interrupt()方法對(duì)其進(jìn)行中斷操作席镀,同時(shí)該線程可以調(diào)用
isInterrupted()來感知其他線程對(duì)其自身的中斷操作匹中,從而做出響應(yīng)。另外豪诲,同樣可以調(diào)用Thread的靜態(tài)方法
interrupted()對(duì)當(dāng)前線程進(jìn)行中斷操作顶捷,該方法會(huì)清除中斷標(biāo)志位。需要注意的是跛溉,當(dāng)拋出InterruptedException時(shí)候焊切,會(huì)清除中斷標(biāo)志位,也就是說在調(diào)用isInterrupted會(huì)返回false芳室。

線程中斷的方法

下面結(jié)合具體的實(shí)例來看一看

public class InterruptDemo {
    public static void main(String[] args) throws InterruptedException {
        //sleepThread睡眠1000ms
        final Thread sleepThread = new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                super.run();
            }
        };
        //busyThread一直執(zhí)行死循環(huán)
        Thread busyThread = new Thread() {
            @Override
            public void run() {
                while (true) ;
            }
        };
        sleepThread.start();
        busyThread.start();
        sleepThread.interrupt();
        busyThread.interrupt();
        while (sleepThread.isInterrupted()) ;
        System.out.println("sleepThread isInterrupted: " + sleepThread.isInterrupted());
        System.out.println("busyThread isInterrupted: " + busyThread.isInterrupted());
    }
}

輸出結(jié)果

sleepThread isInterrupted: false
busyThread isInterrupted: true

開啟了兩個(gè)線程分別為sleepThread和BusyThread, sleepThread睡眠1s专肪,BusyThread執(zhí)行死循環(huán)。然后分別對(duì)著兩個(gè)線程進(jìn)行中斷操作堪侯,可以看出sleepThread拋出InterruptedException后清除標(biāo)志位嚎尤,而busyThread就不會(huì)清除標(biāo)志位。

另外伍宦,同樣可以通過中斷的方式實(shí)現(xiàn)線程間的簡(jiǎn)單交互芽死, while (sleepThread.isInterrupted()) 表示在Main中會(huì)持續(xù)監(jiān)測(cè)sleepThread乏梁,一旦sleepThread的中斷標(biāo)志位清零,即sleepThread.isInterrupted()返回為false時(shí)才會(huì)繼續(xù)Main線程才會(huì)繼續(xù)往下執(zhí)行关贵。因此遇骑,中斷操作可以看做線程間一種簡(jiǎn)便的交互方式。一般在結(jié)束線程時(shí)通過中斷標(biāo)志位或者標(biāo)志位的方式可以有機(jī)會(huì)去清理資源揖曾,相對(duì)于武斷而直接的結(jié)束線程落萎,這種方式要優(yōu)雅和安全。

3.2. join

join方法可以看做是線程間協(xié)作的一種方式炭剪,很多時(shí)候练链,一個(gè)線程的輸入可能非常依賴于另一個(gè)線程的輸出,這就像兩個(gè)好基友奴拦,一個(gè)基友先走在前面突然看見另一個(gè)基友落在后面了媒鼓,這個(gè)時(shí)候他就會(huì)在原處等一等這個(gè)基友,等基友趕上來后错妖,就兩人攜手并進(jìn)绿鸣。其實(shí)線程間的這種協(xié)作方式也符合現(xiàn)實(shí)生活。在軟件開發(fā)的過程中站玄,從客戶那里獲取需求后枚驻,需要經(jīng)過需求分析師進(jìn)行需求分解后濒旦,這個(gè)時(shí)候產(chǎn)品株旷,開發(fā)才會(huì)繼續(xù)跟進(jìn)。如果一個(gè)線程實(shí)例A執(zhí)行了threadB.join(),其含義是:當(dāng)前線程A會(huì)等待threadB線程終止后threadA才會(huì)繼續(xù)執(zhí)行尔邓。關(guān)于join方法一共提供如下這些方法:

public final synchronized void join(long millis)
public final synchronized void join(long millis, int nanos)
public final void join() throws InterruptedException

Thread類除了提供join()方法外晾剖,另外還提供了超時(shí)等待的方法,如果線程threadB在等待的時(shí)間內(nèi)還沒有結(jié)束的話梯嗽,threadA會(huì)在超時(shí)之后繼續(xù)執(zhí)行齿尽。join方法源碼關(guān)鍵是:

 while (isAlive()) {
    wait(0);
 }

可以看出來當(dāng)前等待對(duì)象threadA會(huì)一直阻塞,直到被等待對(duì)象threadB結(jié)束后即isAlive()返回false的時(shí)候才會(huì)結(jié)束while循環(huán)灯节,當(dāng)threadB退出時(shí)會(huì)調(diào)用notifyAll()方法通知所有的等待線程循头。下面用一個(gè)具體的例子來說說join方法的使用:

public class JoinDemo {
    public static void main(String[] args) {
        Thread previousThread = Thread.currentThread();
        for (int i = 1; i <= 10; i++) {
            Thread curThread = new JoinThread(previousThread);
            curThread.start();
            previousThread = curThread;
        }
    }

    static class JoinThread extends Thread {
        private Thread thread;

        public JoinThread(Thread thread) {
            this.thread = thread;
        }

        @Override
        public void run() {
            try {
                thread.join();
                System.out.println(thread.getName() + " terminated.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

輸出結(jié)果為:

main terminated.
Thread-0 terminated.
Thread-1 terminated.
Thread-2 terminated.
Thread-3 terminated.
Thread-4 terminated.
Thread-5 terminated.
Thread-6 terminated.
Thread-7 terminated.
Thread-8 terminated.

在上面的例子中一個(gè)創(chuàng)建了10個(gè)線程,每個(gè)線程都會(huì)等待前一個(gè)線程結(jié)束才會(huì)繼續(xù)運(yùn)行炎疆】睿可以通俗的理解成接力,前一個(gè)線程將接力棒傳給下一個(gè)線程形入,然后又傳給下一個(gè)線程......

3.3 sleep

public static native void sleep(long millis)方法顯然是Thread的靜態(tài)方法全跨,很顯然它是讓當(dāng)前線程按照指定的時(shí)間休眠,其休眠時(shí)間的精度取決于處理器的計(jì)時(shí)器和調(diào)度器亿遂。需要注意的是如果當(dāng)前線程獲得了鎖浓若,sleep方法并不會(huì)失去鎖渺杉。sleep方法經(jīng)常拿來與Object.wait()方法進(jìn)行比價(jià),這也是面試經(jīng)常被問的地方挪钓。

sleep() VS wait()

兩者主要的區(qū)別:

  1. sleep()方法是Thread的靜態(tài)方法是越,而wait是Object實(shí)例方法
  2. wait()方法必須要在同步方法或者同步塊中調(diào)用,也就是必須已經(jīng)獲得對(duì)象鎖碌上。而sleep()方法沒有這個(gè)限制可以在任何地方種使用英妓。另外,wait()方法會(huì)釋放占有的對(duì)象鎖绍赛,使得該線程進(jìn)入等待池中蔓纠,等待下一次獲取資源。而sleep()方法只是會(huì)讓出CPU并不會(huì)釋放掉對(duì)象鎖吗蚌;
  3. sleep()方法在休眠時(shí)間達(dá)到后如果再次獲得CPU時(shí)間片就會(huì)繼續(xù)執(zhí)行腿倚,而wait()方法必須等待Object.notift/Object.notifyAll通知后,才會(huì)離開等待池蚯妇,并且再次獲得CPU時(shí)間片才會(huì)繼續(xù)執(zhí)行敷燎。

3.4 yield

public static native void yield();這是一個(gè)靜態(tài)方法,一旦執(zhí)行箩言,它會(huì)是當(dāng)前線程讓出CPU硬贯,但是,需要注意的是陨收,讓出的CPU并不是代表當(dāng)前線程不再運(yùn)行了饭豹,如果在下一次競(jìng)爭(zhēng)中,又獲得了CPU時(shí)間片當(dāng)前線程依然會(huì)繼續(xù)運(yùn)行务漩。另外拄衰,讓出的時(shí)間片只會(huì)分配給當(dāng)前線程相同優(yōu)先級(jí)的線程。什么是線程優(yōu)先級(jí)了饵骨?下面就來具體聊一聊翘悉。

現(xiàn)代操作系統(tǒng)基本采用時(shí)分的形式調(diào)度運(yùn)行的線程,操作系統(tǒng)會(huì)分出一個(gè)個(gè)時(shí)間片居触,線程會(huì)分配到若干時(shí)間片妖混,當(dāng)前時(shí)間片用完后就會(huì)發(fā)生線程調(diào)度,并等待這下次分配轮洋。線程分配到的時(shí)間多少也就決定了線程使用處理器資源的多少制市,而線程優(yōu)先級(jí)就是決定線程需要或多或少分配一些處理器資源的線程屬性。

在Java程序中砖瞧,通過一個(gè)整型成員變量Priority來控制優(yōu)先級(jí)息堂,優(yōu)先級(jí)的范圍從1~10.在構(gòu)建線程的時(shí)候可以通過setPriority(int)方法進(jìn)行設(shè)置,默認(rèn)優(yōu)先級(jí)為5,優(yōu)先級(jí)高的線程相較于優(yōu)先級(jí)低的線程優(yōu)先獲得處理器時(shí)間片荣堰。需要注意的是在不同JVM以及操作系統(tǒng)上床未,線程規(guī)劃存在差異,有些操作系統(tǒng)甚至?xí)雎跃€程優(yōu)先級(jí)的設(shè)定振坚。

另外需要注意的是薇搁,sleep()和yield()方法,同樣都是當(dāng)前線程會(huì)交出處理器資源渡八,而它們不同的是啃洋,sleep()交出來的時(shí)間片其他線程都可以去競(jìng)爭(zhēng),也就是說都有機(jī)會(huì)獲得當(dāng)前線程讓出的時(shí)間片屎鳍。而yield()方法只允許與當(dāng)前線程具有相同優(yōu)先級(jí)的線程能夠獲得釋放出來的CPU時(shí)間片宏娄。

4.守護(hù)線程Daemon

守護(hù)線程是一種特殊的線程,就和它的名字一樣逮壁,它是系統(tǒng)的守護(hù)者孵坚,在后臺(tái)默默地守護(hù)一些系統(tǒng)服務(wù),比如垃圾回收線程窥淆,JIT線程就可以理解守護(hù)線程卖宠。與之對(duì)應(yīng)的就是用戶線程,用戶線程就可以認(rèn)為是系統(tǒng)的工作線程忧饭,它會(huì)完成整個(gè)系統(tǒng)的業(yè)務(wù)操作扛伍。用戶線程完全結(jié)束后就意味著整個(gè)系統(tǒng)的業(yè)務(wù)任務(wù)全部結(jié)束了,因此系統(tǒng)就沒有對(duì)象需要守護(hù)的了词裤,守護(hù)線程自然而然就會(huì)退刺洒。當(dāng)一個(gè)Java應(yīng)用,只有守護(hù)線程的時(shí)候亚斋,虛擬機(jī)就會(huì)自然退出作媚。下面以一個(gè)簡(jiǎn)單的例子來表述Daemon線程的使用。

public class DaemonDemo {
    public static void main(String[] args) {
        Thread daemonThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        System.out.println("i am alive");
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        System.out.println("finally block");
                    }
                }
            }
        });
        daemonThread.setDaemon(true);
        daemonThread.start();
        //確保main線程結(jié)束前能給daemonThread能夠分到時(shí)間片
        try {
            Thread.sleep(800);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

輸出結(jié)果為:

i am alive
finally block
i am alive

上面的例子中daemodThread run方法中是一個(gè)while死循環(huán)帅刊,會(huì)一直打印,但是當(dāng)main線程結(jié)束后daemonThread就會(huì)退出所以不會(huì)出現(xiàn)死循環(huán)的情況。main線程先睡眠800ms保證daemonThread能夠擁有一次時(shí)間片的機(jī)會(huì)漂问,也就是說可以正常執(zhí)行一次打印“i am alive”操作和一次finally塊中"finally block"操作赖瞒。緊接著main 線程結(jié)束后,daemonThread退出蚤假,這個(gè)時(shí)候只打印了"i am alive"并沒有打印finnal塊中的栏饮。因此,這里需要注意的是守護(hù)線程在退出的時(shí)候并不會(huì)執(zhí)行finnaly塊中的代碼磷仰,所以將釋放資源等操作不要放在finnaly塊中執(zhí)行袍嬉,這種操作是不安全的

線程可以通過setDaemon(true)的方法將線程設(shè)置為守護(hù)線程。并且需要注意的是設(shè)置守護(hù)線程要先于start()方法,否則會(huì)報(bào)

Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.setDaemon(Thread.java:1365)
at learn.DaemonDemo.main(DaemonDemo.java:19)

這樣的異常伺通,但是該線程還是會(huì)執(zhí)行箍土,只不過會(huì)當(dāng)做正常的用戶線程執(zhí)行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末罐监,一起剝皮案震驚了整個(gè)濱河市吴藻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌弓柱,老刑警劉巖沟堡,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異矢空,居然都是意外死亡航罗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門屁药,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伤哺,“玉大人,你說我怎么就攤上這事者祖×⒗颍” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵七问,是天一觀的道長(zhǎng)蜓耻。 經(jīng)常有香客問我,道長(zhǎng)械巡,這世上最難降的妖魔是什么刹淌? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮讥耗,結(jié)果婚禮上有勾,老公的妹妹穿的比我還像新娘。我一直安慰自己古程,他們只是感情好蔼卡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著挣磨,像睡著了一般雇逞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茁裙,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天塘砸,我揣著相機(jī)與錄音,去河邊找鬼晤锥。 笑死掉蔬,一個(gè)胖子當(dāng)著我的面吹牛廊宪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播女轿,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼箭启,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了谈喳?” 一聲冷哼從身側(cè)響起册烈,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎婿禽,沒想到半個(gè)月后赏僧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扭倾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年淀零,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膛壹。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驾中,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出模聋,到底是詐尸還是另有隱情肩民,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布链方,位于F島的核電站持痰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏祟蚀。R本人自食惡果不足惜工窍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望前酿。 院中可真熱鬧患雏,春花似錦、人聲如沸罢维。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)言津。三九已至攻人,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間悬槽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工瞬浓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留初婆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像磅叛,于是被迫代替她去往敵國(guó)和親屑咳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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