Java并發(fā)編程 理解Thread和Object類中線程相關(guān)方法

  1. 為什么線程通信的方法wait()拇颅,notify()和notifyAll()被定義在Object類里校读?而sleep定義在Thread類里再登?
  2. 用3種方式實(shí)現(xiàn)生產(chǎn)者模式
  3. Join和sleep和wait期間線程的狀態(tài)分別是什么耕陷?為什么谜慌?

1. wait,notify,notifyAll方法

作用字旭、用法:阻塞階段对湃、喚醒階段、遇到中斷

1.1阻塞階段
  • 另一個(gè)線程調(diào)用該對(duì)象的notify()方法且剛好被喚醒的是本線程遗淳。
  • 另一個(gè)線程調(diào)用該對(duì)象的notifyAll()方法
  • 過來wait(long timeout)規(guī)定的超時(shí)時(shí)間拍柒,如果傳入0就是永久等待。
  • 線程自身調(diào)用了interrupt()屈暗。

wait,notify,notifyAll作用拆讯、方法

  • 阻塞階段
  • 喚醒階段
  • 遇到中斷

wait、notify

/**
 * 描述:     展示wait和notify的基本用法 1. 研究代碼執(zhí)行順序 2. 證明wait釋放鎖
 */
public class Wait {

    public static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread1 thread1 = new Thread1();
        Thread2 thread2 = new Thread2();
        thread1.start();
        Thread.sleep(200);
        thread2.start();
    }

    static class Thread1 extends Thread {

        @Override
        public void run() {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + "開始執(zhí)行了");
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("線程" + Thread.currentThread().getName() + "獲取到了鎖养叛。");
            }
        }
    }

    static class Thread2 extends Thread {

        @Override
        public void run() {
            synchronized (object) {
                object.notify();
                System.out.println("線程" + Thread.currentThread().getName() + "調(diào)用了notify()");
            }
        }
    }
}
Thread-0開始執(zhí)行了
線程Thread-1調(diào)用了notify()
線程Thread-0獲取到了鎖种呐。
notifyAll
/**
 * 描述:     3個(gè)線程,線程1和線程2首先被阻塞弃甥,線程3喚醒它們爽室。notify, notifyAll。 start先執(zhí)行不代表線程先啟動(dòng)淆攻。
 */
public class WaitNotifyAll implements Runnable {

    private static final Object resourceA = new Object();


    public static void main(String[] args) throws InterruptedException {
        Runnable r = new WaitNotifyAll();
        Thread threadA = new Thread(r);
        Thread threadB = new Thread(r);
        Thread threadC = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resourceA) {
                    resourceA.notifyAll();
//                    resourceA.notify();
                    System.out.println("ThreadC notified.");
                }
            }
        });
        threadA.start();
        threadB.start();
        Thread.sleep(200);
        threadC.start();
    }
    @Override
    public void run() {
        synchronized (resourceA) {
            System.out.println(Thread.currentThread().getName()+" got resourceA lock.");
            try {
                System.out.println(Thread.currentThread().getName()+" waits to start.");
                resourceA.wait();
                System.out.println(Thread.currentThread().getName()+"'s waiting to end.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
Thread-0 got resourceA lock.
Thread-0 waits to start.
Thread-1 got resourceA lock.
Thread-1 waits to start.
ThreadC notified.
Thread-1's waiting to end.
Thread-0's waiting to end.
如果將resourceA.notifyAll() 改為resourceA.notify() 輸出結(jié)果
Thread-0 got resourceA lock.
Thread-0 waits to start.
Thread-1 got resourceA lock.
Thread-1 waits to start.
ThreadC notified.
Thread-0's waiting to end.
wait只釋放當(dāng)前的那把鎖
public class WaitNotifyReleaseOwnMonitor {

    private static volatile Object resourceA = new Object();
    private static volatile Object resourceB = new Object();

    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resourceA) {
                    System.out.println("ThreadA got resourceA lock.");
                    synchronized (resourceB) {
                        System.out.println("ThreadA got resourceB lock.");
                        try {
                            System.out.println("ThreadA releases resourceA lock.");
                            resourceA.wait();

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (resourceA) {
                    System.out.println("ThreadB got resourceA lock.");
                    System.out.println("ThreadB tries to resourceB lock.");

                    synchronized (resourceB) {
                        System.out.println("ThreadB got resourceB lock.");
                    }
                }
            }
        });

        thread1.start();
        thread2.start();
    }
}
ThreadA got resourceA lock.
ThreadA got resourceB lock.
ThreadA releases resourceA lock.
ThreadB got resourceA lock.
ThreadB tries to resourceB lock.

2.生產(chǎn)者消費(fèi)者設(shè)計(jì)模式

產(chǎn)生數(shù)據(jù)的模塊阔墩,就形象地稱為生產(chǎn)者;而處理數(shù)據(jù)的模塊瓶珊,就稱為消費(fèi)者啸箫。
單單抽象出生產(chǎn)者和消費(fèi)者,還夠不上是生產(chǎn)者/消費(fèi)者模式艰毒。該模式還需要有一個(gè)緩沖區(qū)處于生產(chǎn)者和消費(fèi)者之間筐高,作為一個(gè)中介。生產(chǎn)者把數(shù)據(jù)放入緩沖區(qū)丑瞧,而消費(fèi)者從緩沖區(qū)取出數(shù)據(jù)柑土。

為什么要使用生產(chǎn)者和消費(fèi)者模式

  • 解耦:
    假設(shè)生產(chǎn)者和消費(fèi)者分別是兩個(gè)類。如果讓生產(chǎn)者直接調(diào)用消費(fèi)者的某個(gè)方法绊汹,那么生產(chǎn)者對(duì)于消費(fèi)者就會(huì)產(chǎn)生依賴(也就是耦合)稽屏。將來如果消費(fèi)者的代碼發(fā)生變化,可能會(huì)影響到生產(chǎn)者西乖。而如果兩者都依賴于某個(gè)緩沖區(qū)狐榔,兩者之間不直接依賴坛增,耦合也就相應(yīng)降低了。
  • 支持并發(fā):
    生產(chǎn)者直接調(diào)用消費(fèi)者的某個(gè)方法薄腻,還有另一個(gè)弊端收捣。由于函數(shù)調(diào)用是同步的(或者叫阻塞的),在消費(fèi)者的方法沒有返回之前庵楷,生產(chǎn)者只好一直等在那邊罢艾。萬一消費(fèi)者處理數(shù)據(jù)很慢,生產(chǎn)者就會(huì)白白糟蹋大好時(shí)光尽纽。
    使用了生產(chǎn)者/消費(fèi)者模式之后咐蚯,生產(chǎn)者和消費(fèi)者可以是兩個(gè)獨(dú)立的并發(fā)主體(常見并發(fā)類型有進(jìn)程和線程兩種)。生產(chǎn)者把制造出來的數(shù)據(jù)往緩沖區(qū)一丟弄贿,就可以再去生產(chǎn)下一個(gè)數(shù)據(jù)春锋。基本上不用依賴消費(fèi)者的處理速度差凹。其實(shí)當(dāng)初這個(gè)模式期奔,主要就是用來處理并發(fā)問題的。
  • 支持忙閑不均:
    緩沖區(qū)還有另一個(gè)好處直奋。如果制造數(shù)據(jù)的速度時(shí)快時(shí)慢能庆,緩沖區(qū)的好處就體現(xiàn)出來了。當(dāng)數(shù)據(jù)制造快的時(shí)候脚线,消費(fèi)者來不及處理搁胆,未處理的數(shù)據(jù)可以暫時(shí)存在緩沖區(qū)中。等生產(chǎn)者的制造速度慢下來邮绿,消費(fèi)者再慢慢處理掉渠旁。
    環(huán)形緩沖區(qū)(減少了內(nèi)存分配的開銷)
    雙緩沖區(qū)(減少了同步/互斥的開銷)
/**
 * 描述:     用wait/notify來實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式
 */
public class ProducerConsumerModel {
    public static void main(String[] args) {
        EventStorage eventStorage = new EventStorage();
        Producer producer = new Producer(eventStorage);
        Consumer consumer = new Consumer(eventStorage);
        new Thread(producer).start();
        new Thread(consumer).start();
    }
}

class Producer implements Runnable {

    private final EventStorage storage;

    public Producer(
            EventStorage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storage.put();
        }
    }
}

class Consumer implements Runnable {

    private final EventStorage storage;

    public Consumer(
            EventStorage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storage.take();
        }
    }
}

class EventStorage {

    private final int maxSize;
    private final LinkedList<Date> storage;

    public EventStorage() {
        maxSize = 10;
        storage = new LinkedList<>();
    }

    public synchronized void put() {
        while (storage.size() == maxSize) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        storage.add(new Date());
        System.out.println("倉庫里有了" + storage.size() + "個(gè)產(chǎn)品。");
        notify();
    }

    public synchronized void take() {
        while (storage.size() == 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("拿到了" + storage.poll() + "船逮,現(xiàn)在倉庫還剩下" + storage.size());
        notify();
    }
}

倉庫里有了1個(gè)產(chǎn)品顾腊。
倉庫里有了2個(gè)產(chǎn)品。
倉庫里有了3個(gè)產(chǎn)品挖胃。
倉庫里有了4個(gè)產(chǎn)品杂靶。
倉庫里有了5個(gè)產(chǎn)品。
倉庫里有了6個(gè)產(chǎn)品酱鸭。
倉庫里有了7個(gè)產(chǎn)品吗垮。
倉庫里有了8個(gè)產(chǎn)品。
倉庫里有了9個(gè)產(chǎn)品凹髓。
倉庫里有了10個(gè)產(chǎn)品烁登。
拿到了Wed Dec 23 11:44:11 CST 2020,現(xiàn)在倉庫還剩下9
拿到了Wed Dec 23 11:44:11 CST 2020蔚舀,現(xiàn)在倉庫還剩下8
拿到了Wed Dec 23 11:44:11 CST 2020饵沧,現(xiàn)在倉庫還剩下7
拿到了Wed Dec 23 11:44:11 CST 2020锨络,現(xiàn)在倉庫還剩下6
拿到了Wed Dec 23 11:44:11 CST 2020,現(xiàn)在倉庫還剩下5
拿到了Wed Dec 23 11:44:11 CST 2020狼牺,現(xiàn)在倉庫還剩下4
拿到了Wed Dec 23 11:44:11 CST 2020羡儿,現(xiàn)在倉庫還剩下3
拿到了Wed Dec 23 11:44:11 CST 2020,現(xiàn)在倉庫還剩下2
拿到了Wed Dec 23 11:44:11 CST 2020锁右,現(xiàn)在倉庫還剩下1
拿到了Wed Dec 23 11:44:11 CST 2020失受,現(xiàn)在倉庫還剩下0
倉庫里有了1個(gè)產(chǎn)品讶泰。
倉庫里有了2個(gè)產(chǎn)品咏瑟。
...省略
為什么wait()方法要放在同步塊中

防止出現(xiàn)Lost Wake-Up Problem (防止一直wait中)
https://blog.csdn.net/zl1zl2zl3/article/details/89236983
https://www.cnblogs.com/xiohao/p/7118102.html

為什么線程通信的方法wait(),notify()和notifyAll()被定義在Object類里
  • 這些方法存在于同步中痪署;
  • 使用這些方法必須標(biāo)識(shí)同步所屬的鎖码泞;
  • 鎖可以是任意對(duì)象,所以任意對(duì)象調(diào)用方法一定定義在Object類中狼犯。
  • 一個(gè)線程可以加多把鎖

3. sleep方法不釋放鎖

  • 包括synchronized和lock
  • 和wait不同
/**
 * 展示線程sleep的時(shí)候不釋放synchronized的monitor余寥,等sleep時(shí)間到了以后,正常結(jié)束后才釋放鎖
 */
public class SleepDontReleaseMonitor implements Runnable {

    public static void main(String[] args) {
        SleepDontReleaseMonitor sleepDontReleaseMonitor = new SleepDontReleaseMonitor();
        new Thread(sleepDontReleaseMonitor).start();
        new Thread(sleepDontReleaseMonitor).start();
    }

    @Override
    public void run() {
        syn();
    }

    private synchronized void syn() {
        System.out.println("線程" + Thread.currentThread().getName() + "獲取到了monitor悯森。");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("線程" + Thread.currentThread().getName() + "退出了同步代碼塊");
    }
}
線程Thread-1獲取到了monitor宋舷。
線程Thread-1退出了同步代碼塊
線程Thread-0獲取到了monitor。
線程Thread-0退出了同步代碼塊
public class SleepDontReleaseLock implements Runnable {

    private static final Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        SleepDontReleaseLock sleepDontReleaseLock = new SleepDontReleaseLock();
        new Thread(sleepDontReleaseLock).start();
        new Thread(sleepDontReleaseLock).start();
    }

    @Override
    public void run() {
        lock.lock();
        System.out.println("線程" + Thread.currentThread().getName() + "獲取到了鎖");
        try {
            Thread.sleep(5000);
            System.out.println("線程" + Thread.currentThread().getName() + "已經(jīng)蘇醒");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
線程Thread-0獲取到了鎖
線程Thread-0已經(jīng)蘇醒
線程Thread-1獲取到了鎖
線程Thread-1已經(jīng)蘇醒
3.1 sleep方法響應(yīng)中斷
  1. 拋出InterruptedException
  2. 清除中斷狀態(tài)
public class SleepInterrupted implements Runnable {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new SleepInterrupted());
        thread.start();
        Thread.sleep(6500);
        thread.interrupt();
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(new Date());
            try {
                TimeUnit.HOURS.sleep(3);
                TimeUnit.MINUTES.sleep(25);
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("我被中斷了瓢姻!");
                e.printStackTrace();
            }
        }
    }
}
Wed Dec 23 16:24:15 CST 2020
我被中斷了祝蝠!
Wed Dec 23 16:24:22 CST 2020
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at com.kpioneer.thread.threadcoreknowledge.threadobjectclasscommonmethods.SleepInterrupted.run(SleepInterrupted.java:24)
    at java.lang.Thread.run(Thread.java:748)

總結(jié):sleep方法可以讓線程進(jìn)入到Waiting狀態(tài),并且不占用CPU資源幻碱,但是不釋放鎖绎狭,直到規(guī)定時(shí)間后再執(zhí)行,休眠期間如果被中斷褥傍,會(huì)拋出異常并清除中斷狀態(tài)儡嘶。

wait/notify 和 sleep 方法的異同
相同點(diǎn):
  • 它們都可以讓線程阻塞。
  • 它們都可以響應(yīng) interrupt 中斷:在等待的過程中如果收到中斷信號(hào)恍风,都可以進(jìn)行響應(yīng)蹦狂,并拋出 InterruptedException 異常。
不同點(diǎn):
  • wait 方法必須在 synchronized 保護(hù)的代碼中使用朋贬,而 sleep 方法并沒有這個(gè)要求凯楔。
  • 在同步代碼中執(zhí)行 sleep 方法時(shí),并不會(huì)釋放 monitor 鎖兄世,但執(zhí)行 wait 方法時(shí)會(huì)主動(dòng)釋放 monitor 鎖啼辣。
  • sleep 方法中會(huì)要求必須定義一個(gè)時(shí)間,時(shí)間到期后會(huì)主動(dòng)恢復(fù)御滩,而對(duì)于沒有參數(shù)的 wait 方法而言鸥拧,意味著永久等待党远,直到被中斷或被喚醒才能恢復(fù)富弦,它并不會(huì)主動(dòng)恢復(fù)。
  • wait/notify 是 Object 類的方法腕柜,而 sleep 是 Thread 類的方法。

4. join方法

4.1 join方法作用盏缤、用法

作用:因?yàn)樾碌木€程加入了我們,所以我們需要等他執(zhí)行完再出發(fā)
用法:main等待thread1執(zhí)行完畢唉铜,注意誰等誰

4.2 join普通用法
public class Join {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "執(zhí)行完畢");
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "執(zhí)行完畢");
            }
        });

        thread.start();
        thread2.start();
        System.out.println("開始等待子線程運(yùn)行完畢");
        thread.join();
        thread2.join();
        System.out.println("所有子線程執(zhí)行完畢");
    }
}
開始等待子線程運(yùn)行完畢
Thread-1執(zhí)行完畢
Thread-0執(zhí)行完畢
所有子線程執(zhí)行完畢
4.3 join遇到中斷
public class JoinInterrupt {
    public static void main(String[] args) {
        Thread mainThread = Thread.currentThread();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    mainThread.interrupt();
                    Thread.sleep(5000);
                    System.out.println("Thread1 finished.");
                } catch (InterruptedException e) {
                    System.out.println("子線程中斷");
                }
            }
        });
        thread1.start();
        System.out.println("等待子線程運(yùn)行完畢");
        try {
            thread1.join();
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + "主線程中斷了");
        }
        System.out.println("子線程已運(yùn)行完畢");
    }

}
等待子線程運(yùn)行完畢
main主線程中斷了
子線程已運(yùn)行完畢
Thread1 finished.

注意: 發(fā)現(xiàn) 子線程已運(yùn)行完畢又打印了Thread1 finished. 說明子線程 并沒有運(yùn)行完畢

優(yōu)化:在異常中指定子線程中斷thread1.interrupt()

        try {
            thread1.join();
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + "主線程中斷了");
            thread1.interrupt();
        }

樹池

等待子線程運(yùn)行完畢
main主線程中斷了
子線程已運(yùn)行完畢
子線程中斷

Thread1 finished. 沒有打印符合結(jié)果

4.4 在join期間潭流,線程到底是什么狀態(tài)
/**
 * 描述:     先join再mainThread.getState()
 * 通過debugger看線程join前后狀態(tài)的對(duì)比
 */
public class JoinThreadState {
    public static void main(String[] args) throws InterruptedException {
        Thread mainThread = Thread.currentThread();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    System.out.println(mainThread.getState());
                    System.out.println("Thread-0運(yùn)行結(jié)束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        System.out.println("等待子線程運(yùn)行完畢");
        thread.join();
        System.out.println("子線程運(yùn)行完畢");

    }
}
等待子線程運(yùn)行完畢
WAITING
Thread-0運(yùn)行結(jié)束
子線程運(yùn)行完畢

4.5 join等價(jià)實(shí)現(xiàn)
/**
 * 描述:     通過講解join原理,分析出join的代替寫法
 */
public class JoinPrinciple {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "執(zhí)行完畢");
            }
        });

        thread.start();
        System.out.println("開始等待子線程運(yùn)行完畢");
//        thread.join();
        synchronized (thread) {
            thread.wait();
        }
        System.out.println("所有子線程執(zhí)行完畢");
    }
}
開始等待子線程運(yùn)行完畢
Thread-0執(zhí)行完畢
所有子線程執(zhí)行完畢

5 yield方法詳解

作用:釋放我的CPU時(shí)間片
定位:JVM不保證遵循
yield 線程可能再次被調(diào)度

特別感謝

悟空

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拆宛,一起剝皮案震驚了整個(gè)濱河市讼撒,隨后出現(xiàn)的幾起案子浑厚,更是在濱河造成了極大的恐慌,老刑警劉巖椿肩,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞻颂,死亡現(xiàn)場離奇詭異,居然都是意外死亡郑象,警方通過查閱死者的電腦和手機(jī)贡这,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厂榛,“玉大人盖矫,你說我怎么就攤上這事』髂蹋” “怎么了辈双?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長柜砾。 經(jīng)常有香客問我湃望,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任证芭,我火速辦了婚禮瞳浦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘废士。我一直安慰自己叫潦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布官硝。 她就那樣靜靜地躺著矗蕊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪氢架。 梳的紋絲不亂的頭發(fā)上傻咖,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音达箍,去河邊找鬼没龙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛缎玫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播解滓,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼赃磨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了邻辉?” 一聲冷哼從身側(cè)響起值骇,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤吱瘩,失蹤者是張志新(化名)和其女友劉穎使碾,沒想到半個(gè)月后祝懂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年祟剔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹭越。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡响鹃,死狀恐怖买置,靈堂內(nèi)的尸體忽然破棺而出强霎,到底是詐尸還是另有隱情城舞,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布脱柱,位于F島的核電站榨为,受9級(jí)特大地震影響煌茴,放射性物質(zhì)發(fā)生泄漏蔓腐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一绰精、第九天 我趴在偏房一處隱蔽的房頂上張望笨使。 院中可真熱鬧僚害,春花似錦、人聲如沸靶草。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宾袜。三九已至庆猫,卻和暖如春绅络,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背杉畜。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國打工寻行, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人杆烁。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓兔魂,卻偏偏與公主長得像析校,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子遂唧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

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