多線程(一)脯爪、基礎概念及notify()和wait()使用

一启上、基礎概念

1.1碍侦、CPU核心數(shù)和線程數(shù)的關系

多核心 :單芯片多處理器( Chip Multiprocessors,簡稱CMP)棒卷,其思想是將大規(guī)模并行處理器中的SMP(對稱多處理器)集成到同一芯片內(nèi),各個處理器并行執(zhí)行不同的進程。這種依靠多個CPU同時并行地運行程序是實現(xiàn)超高速計算的一個重要方向,稱為并行處理祝钢,

多線程 :讓同一個處理器上的多個線程同步執(zhí)行共享處理器的執(zhí)行資源,可最大限度地實現(xiàn)寬發(fā)射若厚、亂序的超標量處理,提高處理器運算部件的利用率,緩和由于數(shù)據(jù)相關或 Cache未命中帶來的訪問內(nèi)存延時拦英。

二者關系 : 目前CPU基本都是多核,很少看到單核CPU测秸。增加核心數(shù)目就是為了增加線程數(shù),因為操作系統(tǒng)是通過線程來執(zhí)行任務的,一般情況下它們是1:1對應關系,也就是說四核CPU一般擁有四個線程疤估。但Intel引入超線程技術后,使核心數(shù)與線程數(shù)形成1:2的關系.

1.2、時間片輪轉(zhuǎn)機制 (RR 調(diào)度)

定義:系統(tǒng)把所有就緒進程先入先出的原則排成一個隊列霎冯。新來的進程加到就緒隊列末尾铃拇。每當執(zhí)行進程調(diào)度時,進程調(diào)度程序總是選出就緒隊列的隊首進程沈撞,讓它在CPU上運行一個時間片的時間慷荔。時間片是一個小的時間單位,通常為10~100ms數(shù)量級缠俺。當進程用完分給它的時間片后显晶,系統(tǒng)的計時器發(fā)出時鐘中斷,調(diào)度程序便停止該進程的運行壹士,把它放入就緒隊列的末尾磷雇;然后,把CPU分給就緒隊列的隊首進程躏救,同樣也讓它運行一個時間片唯笙,如此往復。

根據(jù)上面CPU核心數(shù)和線程數(shù)的關系 1:1的關系,如果我們手機是雙核手機崩掘,那么我們按道理只能起兩個線程七嫌,但是在實際的開發(fā)過程中并不是這樣,我們可能開了十幾個線程 "同時" 在執(zhí)行呢堰,這是因為操作系統(tǒng)提供了CPU時間片輪轉(zhuǎn)這個機制抄瑟,它為每個進程分配一個時間段(即時間片),讓他們在一段時間內(nèi)交替執(zhí)行枉疼。

上下文切換時間:由于時間片輪轉(zhuǎn)進制皮假,會使得進程之間不停的進行切換,進程之間切換涉及到保存和裝入到寄存器值及內(nèi)存映像骂维,更新表格及隊列惹资,這個過程是需要消耗時間的。

時間片時間設置: 時間片如果設置太短航闺,會導致過多進程不斷切換褪测,由于切換過程會產(chǎn)生上小文切換時間,所以降低CPU效率潦刃,設置太長侮措,又會導致相對較短的交互請求響應變差,通常時間片設置在100ms左右比較合理乖杠。

1.3分扎、進程和線程

1.3.1、什么是進程胧洒?

進程是程序運行資源分配的最小單元

進程是操作系統(tǒng)進行資源分配和調(diào)度的獨立單元畏吓,資源包括CPU,內(nèi)存空間,磁盤IO等等卫漫,同一個進程的所有線程共享該進程的全部資源菲饼,進程與進程之間相互獨立

1.3.2列赎、什么是線程宏悦?

線程是CPU調(diào)度的最小單位,必須依賴進程而存在包吝。

線程是進程的實體肛根,是CPU調(diào)度和分派的基本單位,線程基本不擁有系統(tǒng)資源漏策,但是擁有程序計數(shù)器派哲、一組寄存器、棧等運行中不可少的資源掺喻,同一個進程中的線程共享進程所擁有的全部資源芭届。

1.4储矩、 并發(fā)與并行

1.4.1、什么是并發(fā)

并發(fā)是指一個時間段內(nèi)褂乍,有幾個程序都在同一個CPU上運行持隧,但任意一個時刻點上只有一個程序在處理機上運行。

多個線程 一個CPU

跟時間掛鉤逃片,單位時間內(nèi)屡拨。

1.4.2、什么是并行

并行是指一個時間段內(nèi)褥实,有幾個程序都在幾個CPU上運行呀狼,任意一個時刻點上,有多個程序在同時運行损离,并且多道程序之間互不干擾哥艇。

多個線程 多個CPU

1.5、同步與異步

1.5.1僻澎、什么是同步

同步:在發(fā)出一個同步調(diào)用時貌踏,在沒有得到結(jié)果之前,該調(diào)用就不返回窟勃,直到結(jié)果的返回祖乳。

好比我給朋友打電話,你要不接電話秉氧,我就一直打凡资,這個過程啥也不干,就給你打電話谬运,打到你接電話為止。

1.5.2垦藏、什么是異步

異步:在發(fā)出一個異步調(diào)用后梆暖,調(diào)用者不會立刻得到結(jié)果,該調(diào)用就返回了掂骏。

同樣打電話轰驳,我先給你發(fā)個消息,告訴我有事找你弟灼,然后我就去干我自己的事情去了级解,等你看到消息給我回電話,當然田绑,你也可以不回我電話勤哗。

二、多線程使用

2.1掩驱、創(chuàng)建多線程

2.1.1芒划、實現(xiàn)Runnable接口
    public static class newRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("Runnable");
        }
    }

調(diào)用:

new Thread(new newRunnable()).start();
2.1.2冬竟、繼承Thread類
    public static class newThread extends Thread {
        @Override
        public void run() {
            super.run();
            System.out.println("newThread");
        }
    }

調(diào)用:

new newThread().start();

1、Thread 是java里面對線程的抽象概念民逼,我們通過new thread的時候泵殴,其實只是創(chuàng)建了一個thread實例,操作系統(tǒng)并沒有和該線程掛鉤拼苍,只有執(zhí)行了start方法后笑诅,才是真正意義上啟動了線程。

2疮鲫、start() 會讓一個線程進入就緒隊列等待分配CPU吆你,分到CPU后才調(diào)用 run() 方法,

3棚点、start() 方法不能重復調(diào)用早处,否則會拋出 IllegalThreadStateException 異常。

2.1.3瘫析、實現(xiàn)Callable<V>接口

Callable接口 是在Java1.5開始提供砌梆,可以在任務執(zhí)行結(jié)束后提供返回值。

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

從源碼可以看到贬循,CallableRunnable 對比來看咸包,不同點就在其call方法提供了返回值和進行異常拋出。

使用:

public static class newCallable implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println("newCallable");
            Thread.sleep(3000);
            return "java1.5后提供杖虾,可在任務執(zhí)行結(jié)束返回相應結(jié)果";
        }
    }

對Callable的調(diào)用需要 FutureTask 這個類烂瘫,這個類也是 Java1.5 以后提供

        FutureTask<String> futureTask = new FutureTask<>(new newCallable());
        futureTask.run();
        String result = null;
        try {
            result = futureTask.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

執(zhí)行結(jié)果:

image

可以看到,我們通過 FutureTaskget 方法 奇适,get 方法會進行阻塞坟比,直到任務結(jié)束后,才將返回值進行返回嚷往。

2.2葛账、終止線程

2.2.1、 自然終止

線程任務執(zhí)行完成皮仁,則這個線程進行終止籍琳。

2.2.2、手動終止

暫停贷祈、恢復和停止操作對應在線程Thread的API就是suspend()趋急、resume()和stop()。但是這些API是過期的势誊,也就是不建議使用的呜达,主要原因是方法的調(diào)用不能保證線程資源的正常釋放,容易引起其他副作用的產(chǎn)生粟耻。

image

suspend() :在調(diào)用后闻丑,線程不會釋放已經(jīng)占有的資源(比如鎖)漩怎,而是占有著資源進入睡眠狀態(tài),這樣容易引發(fā)死鎖問題

stop() : 終結(jié)一個線程時不會保證線程的資源正常釋放嗦嗡,通常是沒有給予線程完成資源釋放工作的機會勋锤,因此會導致程序可能工作在不確定狀態(tài)下

真正安全的終止線程使用 interrupt() 方法

image

由于線程之間是協(xié)作式工作,所以在其他線程使用 interrupt() 終止某個線程時候侥祭,這個線程并不會立即終止叁执,只是收到了終止通知,通過檢查自身的中斷標志位是否為被置為 True 再進行相應的操作矮冬,當然谈宛,這個線程完全可以不用理會。

中斷標志位的判斷:

1胎署、isInterrupted()

判斷線程是否中斷吆录,如果該線程已被中斷則返回 true 否則返回 false

    /**
     * Tests whether this thread has been interrupted.  The <i>interrupted
     * status</i> of the thread is unaffected by this method.
     *
     * <p>A thread interruption ignored because a thread was not alive
     * at the time of the interrupt will be reflected by this method
     * returning false.
     *
     * @return  <code>true</code> if this thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see     #interrupted()
     * @revised 6.0
     */
    public boolean isInterrupted() {
        return isInterrupted(false);
    }

2琼牧、interrupted()

判斷線程是否中斷恢筝,如果該線程已被中斷返回 true,狀態(tài)返回后該方法會清除中斷標志位,重新置為 false,當?shù)诙卧俅握{(diào)用的時候又會返回 false 巨坊,(除非重新調(diào)用 interrupt()進行中斷 )

    /**
     * Tests whether the current thread has been interrupted.  The
     * <i>interrupted status</i> of the thread is cleared by this method.  In
     * other words, if this method were to be called twice in succession, the
     * second call would return false (unless the current thread were
     * interrupted again, after the first call had cleared its interrupted
     * status and before the second call had examined it).
     *
     * <p>A thread interruption ignored because a thread was not alive
     * at the time of the interrupt will be reflected by this method
     * returning false.
     *
     * @return  <code>true</code> if the current thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see #isInterrupted()
     * @revised 6.0
     */
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

下面通過一個Demo演示 isInterrupted()interrupted() 的區(qū)別

isInterrupted:

private static class UseThread extends Thread{
        public UseThread(String name) {
            super(name);
        }
        @Override
        public void run() {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName+" interrupt start flag  ="+isInterrupted());
            while(!isInterrupted()){
                System.out.println(threadName+" is running");
                System.out.println(threadName+" inner interrupt flag ="+isInterrupted());
            }
            System.out.println(threadName+" interrupt end flag ="+isInterrupted());
        }
    }

運行上面的程序:

開啟線程撬槽,休眠一微秒后調(diào)用 interrupt() 進行中斷

    public static void main(String[] args) throws InterruptedException {
        Thread endThread = new UseThread("test isInterrupted");
        endThread.start();
        Thread.sleep(1);
        endThread.interrupt();
    }

結(jié)果:

image

可以看到 UseThreadisInterrupted() 一直為 false ,當主線程執(zhí)行 endThread.interrupt() 中斷方法后,其中斷標志被置為 true 趾撵,跳出循環(huán)侄柔,結(jié)束 run 方法。我們后續(xù)再調(diào)用 isInterrupted() 方法打印中斷標志的值一直為 true占调,并沒有更改暂题。

interrupted():

我們簡單改了一下代碼:

 private static class UseThread extends Thread{
        public UseThread(String name) {
            super(name);
        }
        @Override
        public void run() {
            String threadName = Thread.currentThread().getName();

            while(!Thread.interrupted()){
                System.out.println(threadName+" is running");
            }
            System.out.println(threadName+" interrupted end flag ="+Thread.interrupted());
        }
    }

可以看到,run 方法里面一直循環(huán)執(zhí)行究珊,直到線程被中斷薪者,結(jié)束后我們再次調(diào)用了打印了 Thread.interrupted()

調(diào)用:

    public static void main(String[] args) throws InterruptedException {
        Thread endThread = new UseThread("test interrupted");
        endThread.start();
        Thread.sleep(1);
        endThread.interrupt();
    }

同樣休眠一微秒后進行中斷操作。

結(jié)果:

image

我們再分析一下苦银,前面線程結(jié)束循環(huán)的條件是 Thread.interrupted()true , 但是當線程結(jié)束循環(huán)后,我們再次調(diào)用 Thread.interrupted() 方法赶站,發(fā)現(xiàn)其值為又被置為 false 幔虏,說明 Thread.interrupted() 執(zhí)行后,會清除 中斷標志位贝椿,并將其重新置為 false 想括。

注意:處于死鎖狀態(tài)的線程無法被中斷

如果一個線程處于了阻塞狀態(tài)(如線程調(diào)用了thread.sleep、thread.join烙博、thread.wait)瑟蜈,則在線程在檢查中斷標示時如果發(fā)現(xiàn)中斷標示為true烟逊,則會在這些阻塞方法調(diào)用處拋出InterruptedException異常,并且在拋出異常后會立即將線程的中斷標示位清除铺根,即重新設置為false宪躯。

我們在前面 isInterrupted 演示的 Demo中 進行修改

 private static class UseThread extends Thread {
        public UseThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + " interrupt start flag  =" + isInterrupted());
            while (!isInterrupted()) {
                try {
                    // 線程進行休眠3秒
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println("sleep  error=" + e.getLocalizedMessage());
                }
                System.out.println(threadName + " is running");
                System.out.println(threadName + " inner interrupt flag =" + isInterrupted());
            }
            System.out.println(threadName + " interrupt end flag =" + isInterrupted());
        }
    }

我們再執(zhí)行前面的方法的時候,結(jié)果:

image

我們可以看到位迂,即使拋了異常访雪,但是線程依舊在執(zhí)行,這個時候標志位還有沒有置為true掂林,所以我們要注意

拋出InterruptedException異常的時候 對中斷標志位的操作臣缀,我們改一下代碼,在catch中再次執(zhí)行 interrupt()來中斷任務

 try {
       // 線程進行休眠3秒
       Thread.sleep(3000);
    } catch (InterruptedException e) {
      e.printStackTrace();
      // 在catch方法中泻帮,執(zhí)行interrupt() 方法中斷任務精置。
      interrupt();
      System.out.println("sleep  error=" + e.getLocalizedMessage());
   }

結(jié)果:

image

三、線程之間共享和協(xié)作

3.1锣杂、 線程之間共享

前面說過脂倦,同一個進程的所有線程共享該進程的全部資源,共享資源就會導致一個問題蹲堂,當多個線程同時訪問一個對象或者一個對象的成員變量狼讨,可能會導致數(shù)據(jù)不同步問題,比如 線程A 對數(shù)據(jù)a進行操作柒竞,需要從內(nèi)存中進行讀取然后進行相應的操作政供,操作完成后再寫入內(nèi)存中,但是如果數(shù)據(jù)還沒有寫入內(nèi)存中的時候朽基,線程B 也來對這個數(shù)據(jù)進行操作布隔,取到的就是還未寫入內(nèi)存的數(shù)據(jù),導致前后數(shù)據(jù)同步問題稼虎。

為了處理這個問題衅檀,Java 中引入了關鍵字 synchronized ( 下一篇文章單獨講)。

3.2霎俩、線程之間的協(xié)作

線程之間可以相互配合哀军,共同完成一項工作,比如線程A修改了某個值打却,這個時候需要通知另一個線程再執(zhí)行后續(xù)操作杉适,整個過程開始與一個線程,最終又再另一個線程執(zhí)行柳击,前者是生產(chǎn)者猿推,后者就是消費者。

3.2.1捌肴、 nitify()蹬叭、notifyAll()藕咏、wait() 等待/通知機制

是指一個線程A調(diào)用了對象Owait() 方法進入等待狀態(tài),而另一個線程B調(diào)用了對象Onotify()或者notifyAll()方法秽五,線程A收到通知后從對象O的wait()方法返回孽查,進而執(zhí)行后續(xù)操作。上述兩個線程通過對象O來完成交互筝蚕,而對象上的wait()notify卦碾、notifyAll()的關系就如同開關信號一樣,用來完成等待方和通知方之間的交互工作起宽。

我們知道 Object 類是所有類的父類洲胖,而 Object 類中就存在相關方法

image

notify():

通知一個在對象上等待的線程,使其從wait方法返回,而返回的前提是該線程獲取到了對象的鎖,沒有獲得鎖的線程重新進入WAITING狀態(tài)坯沪。

notifyAll():

通知所有等待在該對象上的線程

wait()

調(diào)用該方法的線程進入 WAITING狀態(tài),只有等待另外線程的通知或被中斷才會返回.需要注意,調(diào)用wait()方法后,會釋放對象的鎖

wait(long)

超時等待一段時間,這里的參數(shù)時間是毫秒,也就是等待長達n毫秒,如果沒有通知就超時返回

wait (long,int)

對于超時時間更細粒度的控制,可以達到納秒

下面通過案例說明绿映,雙十一的時候,你購買了三件商品腐晾,你在家焦急的等待叉弦,沒事就刷新一下手機看商品快遞信息,我們就來模擬一個快遞信息的更新藻糖,這里以地點變化進行數(shù)據(jù)更新:

public class NwTest {
    // 發(fā)貨地點
    public String location = "重慶";
    // 所有貨物在不同一趟車上淹冰,貨物到了下一站,分別更新對應的快遞信息
    public synchronized void changeLocationNotify(String location) {
        this.location = location;
        this.notify();
    }
    // 所有貨物在同一趟快遞車上巨柒,貨物到了下一站樱拴,全部信息更新。
    public synchronized void changeLocationNotifyAll(String location) {
        this.location = location;
        System.out.println("changeLocationNotifyAll");
        this.notifyAll();
    }

    public static class LocationThread extends Thread {
        public final NwTest mNwTest;
        public LocationThread(NwTest nwTest) {
            this.mNwTest = nwTest;
        }

        @Override
        public void run() {
            super.run();
            try {
                synchronized (mNwTest) {
                    System.out.println("LocationThread  current location : " + mNwTest.location);   
                    // 等待位置更新
                    mNwTest.wait();
                    String name = Thread.currentThread().getName();
                    // 獲取當前商品的商家信息
                    System.out.println("LocationThread——>current thread name : " + name);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 獲取更新后的位置
            System.out.println("LocationThread  update location : " + mNwTest.location);
        }
    }

注意:

只能在同步方法或者同步塊中使用 wait() 洋满、notifyAll()晶乔、notify() 方法

否則會拋 IllegalMonitorStateException 異常

調(diào)用:

    public static void main(String[] args) throws InterruptedException {
        NwTest nwTest = new NwTest();
        for (int x = 0; x < 3; x++) {
            new LocationThread(nwTest).start();
        }
        // 模擬三天后
        Thread.sleep(3000);
        // 通知單個商品信息進行更新
        nwTest.changeLocationNotify("合肥");
    }

我們啟動了三個線程,模擬了你購買的三件貨物牺勾,如果使用 notify() 正罢,只是使單個商品進行信息更新

結(jié)果:

image

我們看到三個貨物同時發(fā)貨,其中 Thread_0 最先到達合肥驻民,并進行了數(shù)據(jù)更新翻具。

如果使用 notifyAll() ,所有商品快遞信息都會刷新回还。

    public static void main(String[] args) throws InterruptedException {
        NwTest nwTest = new NwTest();
        for (int x = 0; x < 3; x++) {
            new LocationThread(nwTest).start();
        }
        Thread.sleep(3000);
        // 通知三件商品進行信息更新
        nwTest.changeLocationNotifyAll("合肥");
    }

結(jié)果:

image

這就是 notifyAll() 裆泳、 notify()wait() 基本使用懦趋,其中 wait(long) 表示線程會等待 n 毫秒晾虑,如果這個時間段內(nèi)沒有收到 notifyAll() 或者 notify() 就自動執(zhí)行后續(xù)方法疹味。

根據(jù)上面的Demo仅叫,我們可以整理一下 等待和通知的標準范式

wait():

1)獲取對象的鎖帜篇。

2)根據(jù)判斷條件調(diào)用 wait() 方法。

3)條件滿足則執(zhí)行對應的邏輯诫咱。

image

notify() 或者 notifyAll()

1)獲得對象的鎖笙隙。

2)改變條件,發(fā)送通知。

3)通知所有等待在對象上的線程坎缭。

image

以上主要是整理的多線程的一些基本概念竟痰,還有 notify()和wait() 的基本使用,關鍵字 synchronized 準備下一篇單獨整理掏呼,后續(xù)計劃整理線程池相關知識以及Android 中 AsyncTask 的源碼分析坏快,喜歡的話點個贊唄!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末憎夷,一起剝皮案震驚了整個濱河市莽鸿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拾给,老刑警劉巖祥得,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蒋得,居然都是意外死亡级及,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門额衙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來饮焦,“玉大人,你說我怎么就攤上這事入偷∽仿浚” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵疏之,是天一觀的道長殿雪。 經(jīng)常有香客問我,道長锋爪,這世上最難降的妖魔是什么丙曙? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮其骄,結(jié)果婚禮上亏镰,老公的妹妹穿的比我還像新娘。我一直安慰自己拯爽,他們只是感情好索抓,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般逼肯。 火紅的嫁衣襯著肌膚如雪耸黑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天篮幢,我揣著相機與錄音大刊,去河邊找鬼。 笑死三椿,一個胖子當著我的面吹牛缺菌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播搜锰,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼伴郁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蛋叼?” 一聲冷哼從身側(cè)響起蛾绎,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸦列,沒想到半個月后租冠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡薯嗤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年顽爹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骆姐。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡镜粤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出玻褪,到底是詐尸還是另有隱情肉渴,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布带射,位于F島的核電站同规,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏窟社。R本人自食惡果不足惜券勺,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望灿里。 院中可真熱鬧关炼,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琉历。三九已至社痛,卻和暖如春甸祭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背褥影。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咏雌,地道東北人凡怎。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像赊抖,于是被迫代替她去往敵國和親统倒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359