03. 就該這么學(xué)并發(fā) - 線程的阻塞

前言

上章介紹了線程生命周期就緒運(yùn)行狀態(tài)

這章講下線程生命周期中最復(fù)雜的阻塞狀態(tài)

阻塞(Blocked)

在開(kāi)始之前

我們先科普幾個(gè)概念

阻塞,掛起,睡眠 區(qū)分

阻塞

在線程執(zhí)行時(shí),所需要的資源不能立馬得到,則線程被“阻塞”,直到滿(mǎn)足條件則會(huì)繼續(xù)執(zhí)行

阻塞是一種“被動(dòng)”的狀態(tài)

掛起

線程執(zhí)行時(shí),因?yàn)椤爸饔^”需要,需要暫停執(zhí)行當(dāng)前的線程,此時(shí)需要“掛起”當(dāng)前線程.

掛起是“主動(dòng)”的動(dòng)作行為,因?yàn)槭恰爸鲃?dòng)”的,所以“掛起”的線程需要“喚醒”才能繼續(xù)執(zhí)行

睡眠

線程執(zhí)行時(shí),因?yàn)椤爸饔^”需要,需要等待執(zhí)行一段時(shí)間后再繼續(xù)執(zhí)行,
此時(shí)需要讓當(dāng)前線程睡眠一段時(shí)間

睡眠和掛起一樣,也是“主動(dòng)”的動(dòng)作行為,不過(guò)和掛起不一樣的是,它規(guī)定了時(shí)間!

我們舉個(gè)形象的例子來(lái)說(shuō)明

假設(shè)你是個(gè)主人,雇傭了一個(gè)傭人

掛起: 你主動(dòng)對(duì)阿姨說(shuō) “你先去休息,有需要我再喊你”

睡眠: 你主動(dòng)對(duì)阿姨說(shuō) “你去睡兩個(gè)小時(shí),然后繼續(xù)干活”

阻塞: 阿姨自己沒(méi)在干活,因?yàn)楦苫畹墓ぞ卟灰?jiàn)了,等有了工具,她會(huì)自覺(jué)繼續(xù)干活

明白了以上概念,我們繼續(xù)了解,線程什么情況會(huì)阻塞?

線程阻塞原因

對(duì)于線程來(lái)講,當(dāng)發(fā)生如下情況時(shí),線程將會(huì)進(jìn)入阻塞狀態(tài):

  • 線程調(diào)用一個(gè)阻塞式I/O方法,在該方法返回之前,該線程被阻塞

  • 線程試圖獲得一個(gè)同步監(jiān)視器,但該同步監(jiān)視器正被其他線程所持有

  • 線程調(diào)用sleep(): sleep()不會(huì)釋放對(duì)象鎖資源,指定的時(shí)間一過(guò),線程自動(dòng)重新進(jìn)入就緒狀態(tài)

  • 線程調(diào)用wait(): wait()會(huì)釋放持有的對(duì)象鎖,需要notify( )或notifyAll()喚醒

  • 線程調(diào)用suspend()掛起(已廢棄,不推薦使用): resume()(已廢棄,不推薦使用)可以喚醒,使線程重新進(jìn)入就緒狀態(tài)

  • 線程調(diào)用Join()方法: 如線程A中調(diào)用了線程B的Join()方法,直到線程B線程執(zhí)行完畢后,線程A才會(huì)被自動(dòng)喚醒,進(jìn)入就緒狀態(tài)

需要說(shuō)明的是

  • 在阻塞狀態(tài)的線程只能進(jìn)入就緒狀態(tài),無(wú)法直接進(jìn)入運(yùn)行狀態(tài)

  • 就緒和運(yùn)行狀態(tài)之間的轉(zhuǎn)換通常不受程序控制,而是由系統(tǒng)線程調(diào)度所決定

    • 當(dāng)處于就緒狀態(tài)的線程獲得CPU時(shí)間片時(shí),該線程進(jìn)入運(yùn)行狀態(tài);

    • 當(dāng)處于運(yùn)行狀態(tài)的線程失去CPU時(shí)間片時(shí),該線程進(jìn)入就緒狀態(tài);

    • 但有一個(gè)方法例外yield( ):
      使得線程放棄當(dāng)前分得的CPU的時(shí)間片,
      但是不使線程阻塞,即線程仍然處于就緒狀態(tài)
      隨時(shí)可能再次分得CPU的時(shí)間片進(jìn)入執(zhí)行狀態(tài)
      調(diào)用yield()方法可以讓運(yùn)行狀態(tài)的線程轉(zhuǎn)入就緒狀態(tài)

  • sleep()/suspend()/rusume()/yield()均為T(mén)hread類(lèi)的方法,
    wait()/notify()/notifyAll()為Object類(lèi)的方法

對(duì)象鎖 和 監(jiān)視器

細(xì)心的朋友可能注意到以上提到了個(gè)名詞“監(jiān)視器”,和“對(duì)象鎖”,他們是個(gè)啥?

在JVM的規(guī)范中,有這么一些話:

“在JVM中,每個(gè)對(duì)象和類(lèi)在邏輯上都是和一個(gè)監(jiān)視器相關(guān)聯(lián)的”  

“為了實(shí)現(xiàn)監(jiān)視器的排他性監(jiān)視能力,JVM為每一個(gè)對(duì)象和類(lèi)都關(guān)聯(lián)一個(gè)鎖”   

“鎖住了一個(gè)對(duì)象,就是獲得對(duì)象相關(guān)聯(lián)的監(jiān)視器”   

引用一個(gè)流傳很廣的例子來(lái)解釋

可以將監(jiān)視器比作一個(gè)建筑,
它有一個(gè)很特別的房間,
房間里有一些數(shù)據(jù),而且在同一時(shí)間只能被一個(gè)線程占據(jù),
一個(gè)線程從進(jìn)入這個(gè)房間到它離開(kāi)前,它可以獨(dú)占地訪問(wèn)房間中的全部數(shù)據(jù).

進(jìn)入這個(gè)建筑叫做"進(jìn)入監(jiān)視器"
進(jìn)入建筑中的那個(gè)特別的房間叫做"獲得監(jiān)視器"
占據(jù)房間叫做"持有監(jiān)視器"
離開(kāi)房間叫做"釋放監(jiān)視器"
離開(kāi)建筑叫做"退出監(jiān)視器"

而一個(gè)鎖就像一種任何時(shí)候只允許一個(gè)線程擁有的特權(quán),
一個(gè)線程可以允許多次對(duì)同一對(duì)象上鎖,
對(duì)于每一個(gè)對(duì)象來(lái)說(shuō),java虛擬機(jī)維護(hù)一個(gè)計(jì)數(shù)器,記錄對(duì)象被加了多少次鎖,
沒(méi)被鎖的對(duì)象的計(jì)數(shù)器是0, 
線程每加鎖一次,計(jì)數(shù)器就加1,
每釋放一次,計(jì)數(shù)器就減1,
當(dāng)計(jì)數(shù)器跳到0的時(shí)候,鎖就被完全釋放了

Java中使用同步監(jiān)視器的代碼很簡(jiǎn)單,使用關(guān)鍵字 “synchronized”即可

synchronized (obj){            
    //需要同步的代碼
    //obj是同步監(jiān)視器
}
public synchronized void foo(){
    //需同步的代碼        
    //當(dāng)前對(duì)象this是同步監(jiān)視器
}

關(guān)于synchronized的詳細(xì)使用有很多注意點(diǎn), 我們后續(xù)單獨(dú)開(kāi)一章來(lái)講解.

阻塞狀態(tài)分類(lèi)

阻塞分類(lèi).png

根據(jù)阻塞產(chǎn)生的原因不同,阻塞狀態(tài)又可以分為三種:

  • 等待阻塞
運(yùn)行中的線程執(zhí)行wait()方法,該線程會(huì)釋放占用的所有資源對(duì)象,
JVM會(huì)把該線程放入該對(duì)象的“等待隊(duì)列”中,進(jìn)入這個(gè)狀態(tài)后,是不能自動(dòng)喚醒的,
必須依靠其他線程調(diào)用notify()或notifyAll()方法才能被喚醒,
喚醒后進(jìn)入“阻塞(同步隊(duì)列)”
  • 同步阻塞
就緒狀態(tài)的線程,被分配了CPU時(shí)間片,
準(zhǔn)備執(zhí)行時(shí)發(fā)現(xiàn)需要的資源對(duì)象被synchroniza(同步)(資源對(duì)象被其它線程鎖住占用了),
獲取不到鎖標(biāo)記,該線程將會(huì)立即進(jìn)入鎖池狀態(tài),等待獲取鎖標(biāo)記,
這時(shí)的鎖池里,也許已經(jīng)有了其他線程在等待獲取鎖標(biāo)記,
這時(shí)它們處于隊(duì)列狀態(tài),既先到先得
一旦線程獲得鎖標(biāo)記后,就轉(zhuǎn)入就緒狀態(tài),繼續(xù)等待CPU時(shí)間片
  • 其他阻塞
運(yùn)行的線程調(diào)用了自身的sleep()方法或其他線程的join()方法,
或者發(fā)出了I/O請(qǐng)求時(shí),JVM會(huì)把該線程置為阻塞狀態(tài).
當(dāng)sleep()狀態(tài)超時(shí)曹体、join()等待線程終止或者超時(shí)、
或者I/O處理完畢時(shí),線程重新轉(zhuǎn)入就緒狀態(tài),等待CPU分配時(shí)間片執(zhí)行

Thread類(lèi)相關(guān)方法介紹

看完以上阻塞的介紹,可能很多朋友對(duì)Thread類(lèi)的一些方法產(chǎn)生了疑問(wèn),下面我們來(lái)實(shí)際探究下這些方法的使用,相關(guān)的注意點(diǎn)我就直接寫(xiě)在注釋中方便閱讀

public class Thread{
    // 線程的啟動(dòng)
    public void start(); 
    // 線程體,線程需要做的事
    public void run(); 
    // 已廢棄,停止線程
    public void stop(); 
    // 已廢棄,掛起線程,(不釋放對(duì)象鎖)
    public void suspend(); 
    // 已廢棄,喚醒掛起的線程
    public void resume(); 
    // 在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(不釋放對(duì)象鎖)
    public static void sleep(long millis); 
    // 同上,增加了納秒?yún)?shù)(不釋放對(duì)象鎖)
    public static void sleep(long millis,int nanos); 
    //線程讓步(不釋放對(duì)象鎖)
    public static void yield();
    // 測(cè)試線程是否處于活動(dòng)狀態(tài)
    public boolean isAlive(); 
    // 中斷線程
    public void interrupt(); 
    // 測(cè)試線程是否已經(jīng)中斷
    public boolean isInterrupted(); 
    // 測(cè)試當(dāng)前線程是否已經(jīng)中斷
    public static boolean interrupted(); 
    // 等待該線程終止
    public void join() throws InterruptedException; 
    // 等待該線程終止的時(shí)間最長(zhǎng)為 millis 毫秒
    public void join(long millis) throws InterruptedException; 
    // 等待該線程終止的時(shí)間最長(zhǎng)為 millis 毫秒 + nanos 納秒
    public void join(long millis,int nanos) throws InterruptedException; 
}

我們可以看出,Thread類(lèi)很多方法因?yàn)榫€程安全問(wèn)題已經(jīng)被棄用了,比如我們講的suspend()/resume(), 因?yàn)樗鼤?huì)產(chǎn)生死鎖

現(xiàn)在

掛起是JVM的系統(tǒng)行為,我們無(wú)需干涉

suspend()/resume()產(chǎn)生死鎖的原因

當(dāng)suspend()的線程持有某個(gè)對(duì)象鎖,而resume()它的線程又正好需要使用此鎖的時(shí)候,死鎖就產(chǎn)生了

舉個(gè)例子:

有兩個(gè)線程A和B,以及一個(gè)公共資源O

A執(zhí)行時(shí)需要O對(duì)象,所以A拿到了O鎖住,防止操作時(shí)O再被別的線程拿走,之后suspend掛起,

B呢,負(fù)責(zé)在適當(dāng)?shù)臅r(shí)候resume喚醒A,但是B執(zhí)行時(shí)也需要拿到O對(duì)象

此時(shí),死鎖產(chǎn)生了

A拿著O掛起,因?yàn)閞esume的實(shí)現(xiàn)機(jī)制,所以掛起時(shí)O不會(huì)被釋放,

只有A被resume喚醒繼續(xù)執(zhí)行完畢才能釋放O,

B本來(lái)負(fù)責(zé)喚醒A,但是B又拿不到O,

所以,A和B永遠(yuǎn)都在等待,執(zhí)行不了

說(shuō)到Thread類(lèi)的suspend和/resume,順帶也提下Object類(lèi)的wait/notify這對(duì)組合,wait/notify屬于對(duì)象方法,意味著所有對(duì)象都會(huì)有這兩個(gè)方法.

wait/notify

這兩個(gè)方法同樣是等待/通知,但使用它們的前提是已經(jīng)獲得了鎖,且在wait(等待)期間會(huì)釋放鎖

線程要調(diào)用wait(),必須先獲得該對(duì)象的鎖,在調(diào)用wait()之后,當(dāng)前線程釋放該對(duì)象鎖并進(jìn)入休眠,只有以下幾種情況下會(huì)被喚醒

- 其他線程調(diào)用了該對(duì)象的notify()(隨機(jī)喚醒等待隊(duì)列的一個(gè)線程)
或notifyAll()(隨機(jī)等待隊(duì)列的所有線程); 

- 當(dāng)前線程被中斷; 

- 調(diào)用wait(3000)時(shí)指定的時(shí)間(3s)已到.

類(lèi)方法和對(duì)象方法區(qū)別( sleep() & wait() )

這里重點(diǎn)再?gòu)?qiáng)調(diào)下類(lèi)方法和對(duì)象方法的區(qū)別,我們以sleepwait為例

sleep方法是Thread類(lèi)靜態(tài)方法,直接使用Thread.sleep()就可以調(diào)用

最好不要用Thread的實(shí)例對(duì)象調(diào)用它,因?yàn)樗叩氖冀K是當(dāng)前正在運(yùn)行的線程

它只對(duì)正在運(yùn)行狀態(tài)的線程對(duì)象有效

使用sleep方法時(shí),一定要用try catch處理InterruptedException異常

我們舉個(gè)例子

//定義一個(gè)線程類(lèi)
public class ImpRunnableThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println("線程: " +  Thread.currentThread().getName() + "第" + i + "次執(zhí)行攘乒!");
        }
    }
}

//測(cè)試
class Test {
    public void main(String[] args){
    Thread t = new Thread(new ImpRunnableThread());
     t.start();
     //很多人會(huì)以為睡眠的是t線程,但其實(shí)是main線程
     t.sleep(5000);
     for (int i = 0; i < 3; i++) {
          System.out.println("線程: " +    Thread.currentThread().getName() + "第" + i + "次執(zhí)行!");
    }
}

先不說(shuō)直接 “對(duì)象.sleep()” 這種使用方式本就不對(duì),

再者 t.sleep(5000)很多人會(huì)以為是讓t線程睡眠5s,

但其實(shí)睡眠的是main線程!

我們執(zhí)行代碼,就可以看出,t線程會(huì)先執(zhí)行完畢,5s后主線程才會(huì)輸出!

那么問(wèn)題來(lái)了,如何讓t線程睡眠呢??

很簡(jiǎn)單,我們?cè)贗mpRunnableThread類(lèi)的run()方法中寫(xiě)sleep()即可!

public class ImpRunnableThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            //sleep()一定要try catch
            try {
                if (i == 2) {
                    //t線程睡眠5s
                    Thread.sleep(5000);
                }
                System.out.println("線程: " + Thread.currentThread().getName() + "第" + i + "次執(zhí)行碳竟!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }}}
}

說(shuō)完類(lèi)方法,我們?cè)僬f(shuō)對(duì)象方法

對(duì)象鎖: 即針對(duì)一個(gè)“實(shí)例對(duì)象”的鎖,java中,所有的對(duì)象都可以“鎖住”,這里舉個(gè)簡(jiǎn)單的例子

//實(shí)例一個(gè)Object對(duì)象
Object lock = new Object();
//使用synchronized將lock對(duì)象鎖住
synchronized(lock){
    //鎖保護(hù)的代碼塊
}

在Object對(duì)象中有三個(gè)方法wait()蜜徽、notify()腋么、notifyAll()

  • wait()
wait()方法可以使調(diào)用該方法的線程釋放共享資源的鎖,
然后從運(yùn)行狀態(tài)退出,進(jìn)入阻塞(等待隊(duì)列),直到再次被喚醒(進(jìn)入阻塞(同步隊(duì)列)).

這里需要注意,形如wait(3000)這樣的帶參構(gòu)造,
無(wú)需其它線程notify()或notifyAll()喚醒,到了時(shí)間會(huì)自動(dòng)喚醒,
看似和sleep(3000)一樣,但其實(shí)是不同的
wait(3000)調(diào)用時(shí)會(huì)釋放對(duì)象鎖,3s過(guò)后,進(jìn)入阻塞(同步隊(duì)列),
競(jìng)爭(zhēng)到對(duì)象鎖后進(jìn)入就緒狀態(tài),而后cpu調(diào)度執(zhí)行.
所以,實(shí)際等待時(shí)間比3s會(huì)長(zhǎng)!!

而sleep(3000),不會(huì)釋放對(duì)象鎖,
3s過(guò)后,直接進(jìn)入就緒狀態(tài),等待cpu調(diào)度執(zhí)行.
  • notify()
notify()方法可以隨機(jī)喚醒阻塞(等待隊(duì)列)中等待同一共享資源的一個(gè)線
程,并使得該線程退出等待狀態(tài),進(jìn)入阻塞(同步隊(duì)列)
  • notifyAll()
notifyAll()和notify()類(lèi)似,不過(guò)它喚醒了阻塞(等待隊(duì)列)中等待
同一共享資源的所有線程

最后,如果wait()方法和notify()/notifyAll()方法不在同步方法/同步代碼塊中被調(diào)用,那么虛擬機(jī)會(huì)拋出

java.lang.IllegalMonitorStateException

接下來(lái)我們來(lái)看看具體任何使用

定義一個(gè)等待線程WaitThread

class WaitThread extends Thread {
    private Object lock;

    public WaitThread(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        try {
            synchronized (lock) {
                System.out.println(
                        "start---" + Thread.currentThread().getName() + "---wait time = " + System.currentTimeMillis());
                lock.wait();
                System.out.println(
                        "end---" + Thread.currentThread().getName() + "---wait time = " + System.currentTimeMillis());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

定義一個(gè)喚醒線程N(yùn)otifyThread

class NotifyThread extends Thread {
    private Object lock;

    public NotifyThread(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            System.out.println(
                    "start---" + Thread.currentThread().getName() + "---wait time = " + System.currentTimeMillis());
            lock.notify();
            System.out.println(
                    "end---" + Thread.currentThread().getName() + "---wait time = " + System.currentTimeMillis());
        }
    }
}

測(cè)試代碼

public class Test {
    public static void main(String[] args) throws Exception {
        Object lock = new Object();
        WaitThread w1 = new WaitThread(lock);
        w1.setName("等待線程");
        w1.start(); 
        //main線程睡眠3s,便于我們看到效果
        Thread.sleep(3000);
        NotifyThread n1 = new NotifyThread(lock);
        n1.setName("喚醒線程");
        n1.start();
    }
}

結(jié)果

start---等待線程---wait time = 1589425525994
start---喚醒線程---wait time = 1589425529001
end---喚醒線程---wait time = 1589425529001
end---等待線程---wait time = 1589425529001

結(jié)果可以看出,等待線程被喚醒線程喚醒后才繼續(xù)輸出.
需要注意的是,如果等待線程設(shè)置的是wait(3000),則無(wú)需喚醒線程喚醒,它自己在3s后會(huì)繼續(xù)執(zhí)行.

等待隊(duì)列 & 同步隊(duì)

前面一直提到兩個(gè)概念,等待隊(duì)列(等待池),同步隊(duì)列(鎖池),這兩者是不一樣的.具體如下:

同步隊(duì)列(鎖池)

假設(shè)線程A已經(jīng)擁有了某個(gè)對(duì)象(注意:不是類(lèi))的鎖,
而其它的線程想要調(diào)用這個(gè)對(duì)象的某個(gè)synchronized方法(或者synchronized塊),
由于這些線程在進(jìn)入對(duì)象的synchronized方法之前必須先獲得該對(duì)象的鎖的擁有權(quán),
但是該對(duì)象的鎖目前正被線程A擁有,
所以這些線程就進(jìn)入了該對(duì)象的同步隊(duì)列(鎖池)中,
這些線程狀態(tài)為Blocked.

等待隊(duì)列(等待池)

假設(shè)一個(gè)線程A調(diào)用了某個(gè)對(duì)象的wait()方法,
線程A就會(huì)釋放該對(duì)象的鎖
(因?yàn)閣ait()方法必須出現(xiàn)在synchronized中,
這樣自然在執(zhí)行wait()方法之前線程A就已經(jīng)擁有了該對(duì)象的鎖),
同時(shí) 線程A就進(jìn)入到了該對(duì)象的等待隊(duì)列(等待池)中,
此時(shí)線程A狀態(tài)為Waiting.
如果另外的一個(gè)線程調(diào)用了相同對(duì)象的notifyAll()方法,
那么處于該對(duì)象的等待池中的線程
就會(huì)全部進(jìn)入該對(duì)象的同步隊(duì)列(鎖池)中,準(zhǔn)備爭(zhēng)奪鎖的擁有權(quán).
如果另外的一個(gè)線程調(diào)用了相同對(duì)象的notify()方法,
那么僅僅有一個(gè)處于該對(duì)象的等待池中的線程(隨機(jī))會(huì)進(jìn)入該對(duì)象的同步隊(duì)列(鎖池)

notify()notifyAll()喚起的線程是有規(guī)律

- 如果是通過(guò)notify來(lái)喚起的線程,那 先進(jìn)入wait的線程會(huì)先被喚起來(lái);

- 如果是通過(guò)nootifyAll喚起的線程,默認(rèn)情況是 最后進(jìn)入的會(huì)先被喚起來(lái),即LIFO的策略腾么;

請(qǐng)關(guān)注我的訂閱號(hào)

訂閱號(hào).png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奈梳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子解虱,更是在濱河造成了極大的恐慌攘须,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件殴泰,死亡現(xiàn)場(chǎng)離奇詭異于宙,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)悍汛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)限煞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人员凝,你說(shuō)我怎么就攤上這事署驻。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵旺上,是天一觀的道長(zhǎng)瓶蚂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)宣吱,這世上最難降的妖魔是什么窃这? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮征候,結(jié)果婚禮上杭攻,老公的妹妹穿的比我還像新娘。我一直安慰自己疤坝,他們只是感情好兆解,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著跑揉,像睡著了一般锅睛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上历谍,一...
    開(kāi)封第一講書(shū)人閱讀 51,775評(píng)論 1 307
  • 那天现拒,我揣著相機(jī)與錄音,去河邊找鬼望侈。 笑死印蔬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的脱衙。 我是一名探鬼主播扛点,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼岂丘!你這毒婦竟也來(lái)了陵究?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤奥帘,失蹤者是張志新(化名)和其女友劉穎铜邮,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體寨蹋,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡松蒜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了已旧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秸苗。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖运褪,靈堂內(nèi)的尸體忽然破棺而出惊楼,到底是詐尸還是另有隱情玖瘸,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布檀咙,位于F島的核電站雅倒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏弧可。R本人自食惡果不足惜蔑匣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望棕诵。 院中可真熱鬧裁良,春花似錦、人聲如沸校套。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)搔确。三九已至彼棍,卻和暖如春灭忠,著一層夾襖步出監(jiān)牢的瞬間膳算,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工弛作, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涕蜂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓映琳,卻偏偏與公主長(zhǎng)得像机隙,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子萨西,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356