單例模式與多線程

本文的知識(shí)點(diǎn)非常重要窟社,通過(guò)單例模式與多線程技術(shù)相結(jié)合,在這個(gè)過(guò)程中能發(fā)現(xiàn)很多以前未考慮過(guò)的情況手幢,一些不良的程序設(shè)計(jì)方法如果應(yīng)用在商業(yè)項(xiàng)目中,將會(huì)遇到非常大的麻煩娃闲。本文的案例也將充分說(shuō)明虚汛,線程與某些技術(shù)相結(jié)合時(shí)要考慮的事情有很多。在學(xué)習(xí)本文時(shí)只需要考慮一件事情皇帮,那就是:如何使單例模式遇到多線程是安全的卷哩、正確的。

在標(biāo)準(zhǔn)的23個(gè)設(shè)計(jì)模式中属拾,單例設(shè)計(jì)模式在應(yīng)用中是比較常見(jiàn)的将谊。但在常規(guī)的該模式教學(xué)資料介紹中,多數(shù)并沒(méi)有結(jié)合多線程技術(shù)作為參考渐白,這就造成在使用多線程技術(shù)的單例模式時(shí)會(huì)出現(xiàn)一些意想不到的情況尊浓,這樣的代碼如果在生產(chǎn)環(huán)境中出現(xiàn)異常,有可能造成災(zāi)難性的后果纯衍。本文將介紹單例模式結(jié)合多線程技術(shù)在使用時(shí)的相關(guān)知識(shí)栋齿。

1. 立即加載/“餓漢模式”

什么是立即加載?立即加載就是使用類(lèi)的時(shí)候已經(jīng)將對(duì)象創(chuàng)建完畢襟诸,常見(jiàn)的實(shí)現(xiàn)辦法就是直接new實(shí)例化瓦堵。而立即加載從中文的語(yǔ)境來(lái)看,有“著急”歌亲、“急迫”的含義菇用,所以也稱(chēng)為“餓漢模式”。
立即加載/“餓漢模式”是在調(diào)用方法前陷揪,實(shí)例已經(jīng)被創(chuàng)建了惋鸥,來(lái)看一下實(shí)現(xiàn)代碼。

創(chuàng)建測(cè)試用的項(xiàng)目鹅龄,創(chuàng)建類(lèi)MyObject.java代碼如下:

public class MyObject {

    // 立即加載方式==餓漢模式
    private static MyObject myObject = new MyObject();

    private MyObject() {
    }

    public static MyObject getInstance() {
        // 此代碼版本為立即加載
        // 此版本代碼的缺點(diǎn)是不能有其它實(shí)例變量
        // 因?yàn)間etInstance()方法沒(méi)有同步
        // 所以有可能出現(xiàn)非線程安全問(wèn)題
        return myObject;
    }

}

創(chuàng)建線程類(lèi)MyThread.java代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println(MyObject.getInstance().hashCode());
    }

}

創(chuàng)建運(yùn)行類(lèi)Run.java代碼如下:

import extthread.MyThread;

public class Run {

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.start();
        t2.start();
        t3.start();

    }

}

程序運(yùn)行后的結(jié)果如下:

1031548957
1031548957
1031548957

控制臺(tái)打印的hashCode是同一個(gè)只揩慕,說(shuō)明對(duì)象是同一個(gè),也就實(shí)現(xiàn)了立即加載型單例設(shè)計(jì)模式扮休。

2. 延遲加載/“懶漢模式”

什么是延遲加載?延遲加載就是在調(diào)用get()方法時(shí)實(shí)例才被創(chuàng)建拴鸵,常見(jiàn)的實(shí)現(xiàn)辦法就是在get()方法中進(jìn)行new實(shí)例化玷坠。而延遲加載從中文的語(yǔ)境來(lái)看,是“緩慢”劲藐、“不急迫”的含義八堡,所以也稱(chēng)為“懶漢模式”。

2.1 延遲加載/“懶漢模式”解析

延遲加載/“懶漢模式”是在調(diào)用方法時(shí)實(shí)例才被創(chuàng)建聘芜。一起來(lái)看一下實(shí)現(xiàn)代碼兄渺。

創(chuàng)建類(lèi)MyObject.java代碼如下:

public class MyObject {

    private static MyObject myObject;

    private MyObject() {
    }

    public static MyObject getInstance() {
        // 延遲加載
        if (myObject != null) {
        } else {
            myObject = new MyObject();
        }
        return myObject;
    }

}

創(chuàng)建線程類(lèi)MyThread.java代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println(MyObject.getInstance().hashCode());
    }

}

創(chuàng)建運(yùn)行類(lèi)Run.java代碼如下:

import extthread.MyThread;

public class Run {

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        t1.start();
    }

}

程序運(yùn)行后的效果如下:

1031548957

此實(shí)驗(yàn)雖然取得一個(gè)對(duì)象的實(shí)例,但如果是在多線程的環(huán)境中汰现,就會(huì)出現(xiàn)去除多個(gè)實(shí)例的情況挂谍,與單例模式的初衷是相背離的叔壤。

2.2 延遲加載/“懶漢模式”的缺點(diǎn)

前面兩個(gè)實(shí)驗(yàn)雖然使用“立即加載”和“延遲加載”實(shí)現(xiàn)了單例設(shè)計(jì)模式,但在多線程的環(huán)境中口叙,前面“延遲加載”示例中的代碼完全就是錯(cuò)誤的炼绘,根本補(bǔ)鞥呢實(shí)現(xiàn)保持單例的狀態(tài)。來(lái)看一下如何在多線程環(huán)境中結(jié)合“錯(cuò)誤的單例模式”創(chuàng)建出“多例”妄田。
創(chuàng)建類(lèi)MyObject.java代碼如下:

public class MyObject {

    private static MyObject myObject;

    private MyObject() {
    }

    public static MyObject getInstance() {
        try {
            if (myObject != null) {
            } else {
                // 模擬在創(chuàng)建對(duì)象之前做一些準(zhǔn)備性的工作
                Thread.sleep(3000);
                myObject = new MyObject();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }

}

創(chuàng)建線程類(lèi)MyThread.java代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println(MyObject.getInstance().hashCode());
    }

}

創(chuàng)建運(yùn)行類(lèi)Run.java代碼如下:

import extthread.MyThread;

public class Run {

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.start();
        t2.start();
        t3.start();

    }

}

程序運(yùn)行后的效果如下:

186668687
903341402
1770731361

控制臺(tái)打印出了3中hashCode俺亮,說(shuō)明創(chuàng)建了3個(gè)對(duì)象,并不是單例的疟呐,這就是“錯(cuò)誤的單例模式”脚曾。如何解決呢?先看一下解決方案启具。

2.3 延遲加載/“懶漢模式”的解決方案

2.3.1 聲明synchronized關(guān)鍵字

既然多個(gè)線程可以同時(shí)進(jìn)入getInstance()方法斟珊,那么只需要對(duì)getInstance()方法聲明synchronized關(guān)鍵字即可。

創(chuàng)建類(lèi)MyObject.java代碼如下:

public class MyObject {

    private static MyObject myObject;

    private MyObject() {
    }

    // 設(shè)置同步方法效率太低了
    // 整個(gè)方法被上鎖
    synchronized public static MyObject getInstance() {
        try {
            if (myObject != null) {
            } else {
                // 模擬在創(chuàng)建對(duì)象之前做一些準(zhǔn)備性的工作
                Thread.sleep(3000);
                myObject = new MyObject();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }

}

創(chuàng)建線程類(lèi)MyThread.java代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println(MyObject.getInstance().hashCode());
    }

}

創(chuàng)建運(yùn)行類(lèi)Run.java代碼如下:

import extthread.MyThread;

public class Run {

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.start();
        t2.start();
        t3.start();

    }

}

程序運(yùn)行后的結(jié)果如下:

531436928
531436928
531436928

此方法加入同步synchronized關(guān)鍵字得到相同實(shí)例的對(duì)象富纸,但此種方法的運(yùn)行效率非常低下囤踩,是同步運(yùn)行的,下一個(gè)線程想要取得對(duì)象晓褪,則必須等上一個(gè)線程釋放鎖之后堵漱,才可以繼續(xù)執(zhí)行。

2.3.2 嘗試同步代碼塊

同步方法是對(duì)方法的整體進(jìn)行持鎖涣仿,這對(duì)運(yùn)行效率來(lái)講是不利的勤庐。改成同步代碼塊能解決嗎?

創(chuàng)建類(lèi)MyObject.java代碼如下:

public class MyObject {

    private static MyObject myObject;

    private MyObject() {
    }

    public static MyObject getInstance() {
        try {
            // 此種寫(xiě)法等同于:
            // synchronized public static MyObject getInstance()
            // 的寫(xiě)法好港,效率一樣很低愉镰,全部代碼被上鎖
            synchronized (MyObject.class) {
                if (myObject != null) {
                } else {
                    // 模擬在創(chuàng)建對(duì)象之前做一些準(zhǔn)備性的工作
                    Thread.sleep(3000);

                    myObject = new MyObject();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }

}

創(chuàng)建線程類(lèi)MyThread.java代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println(MyObject.getInstance().hashCode());
    }

}

創(chuàng)建運(yùn)行類(lèi)Run.java代碼如下:

import extthread.MyThread;

public class Run {

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.start();
        t2.start();
        t3.start();

        // 此版本代碼雖然是正確的
        // 但public static MyObject getInstance()方法
        // 中的全部代碼都是同步的了,這樣做有損效率
    }

}

程序運(yùn)行后的結(jié)果如下:

903341402
903341402
903341402

此方法加入同步synchronized語(yǔ)句塊得到相同實(shí)例的對(duì)象钧汹,但此種方法的運(yùn)行效率也是非常低的丈探,和synchronized同步方法一樣是同步運(yùn)行的。繼續(xù)更改代碼嘗試解決這個(gè)缺點(diǎn)拔莱。

2.3.3 針對(duì)某些重要的代碼進(jìn)行單獨(dú)的同步

同步代碼塊可以針對(duì)某些重要的代碼進(jìn)行單獨(dú)的同步碗降,而其他的代碼則不需要同步。這樣在運(yùn)行時(shí)塘秦,效率完全可以得到大幅提升讼渊。

創(chuàng)建MyObject.java代碼如下:

public class MyObject {

    private static MyObject myObject;

    private MyObject() {
    }

    public static MyObject getInstance() {
        try {
            if (myObject != null) {
            } else {
                // 模擬在創(chuàng)建對(duì)象之前做一些準(zhǔn)備性的工作
                Thread.sleep(3000);
                // 使用synchronized (MyObject.class)
                // 雖然部分代碼被上鎖
                // 但還是有非線程安全問(wèn)題
                synchronized (MyObject.class) {
                    myObject = new MyObject();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }

}

創(chuàng)建線程類(lèi)MyThread.java代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println(MyObject.getInstance().hashCode());
    }

}

創(chuàng)建運(yùn)行類(lèi)Run.java代碼如下:

import extthread.MyThread;

public class Run {

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.start();
        t2.start();
        t3.start();

    }

}

程序運(yùn)行后的結(jié)果如下:

903341402
1770731361
1684444739

此方法使同步synchronized語(yǔ)句塊,只對(duì)實(shí)例化對(duì)象的關(guān)鍵代碼進(jìn)行同步尊剔,從語(yǔ)句的結(jié)構(gòu)上來(lái)講爪幻,運(yùn)行的效率的確得到了提升。但如果是遇到多線程的情況下無(wú)法解決得到同一個(gè)實(shí)例對(duì)象的結(jié)果。到底如何解決“懶漢模式”遇到多線程的情況呢挨稿?

2.3.4 使用DCL雙檢查鎖機(jī)制

在最后的步驟中仇轻,使用的是DCL雙檢查鎖機(jī)制來(lái)實(shí)現(xiàn)多線程環(huán)境中的延遲加載單例設(shè)計(jì)模式。

創(chuàng)建類(lèi)MyObject.java代碼如下:

public class MyObject {

    private volatile static MyObject myObject;

    private MyObject() {
    }

    // 使用雙檢測(cè)機(jī)制來(lái)解決問(wèn)題
    // 即保證了不需要同步代碼的異步
    // 又保證了單例的效果
    public static MyObject getInstance() {
        try {
            if (myObject != null) {
            } else {
                // 模擬在創(chuàng)建對(duì)象之前做一些準(zhǔn)備性的工作
                Thread.sleep(3000);
                synchronized (MyObject.class) {
                    if (myObject == null) {
                        myObject = new MyObject();
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }
    // 此版本的代碼稱(chēng)為:
    // 雙重檢查Double-Check Locking

}

創(chuàng)建線程類(lèi)MyThread.java代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println(MyObject.getInstance().hashCode());
    }

}

創(chuàng)建運(yùn)行類(lèi)Run.java代碼如下:

import extthread.MyThread;

public class Run {

    public static void main(String[] args) {
        
        
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.start();
        t2.start();
        t3.start();

    }

}

程序運(yùn)行后的結(jié)果如下:

186668687
186668687
186668687

使用雙重檢查鎖功能叶组,成功地解決了“懶漢模式”遇到多線程的問(wèn)題拯田。DCL也是大多數(shù)多線程結(jié)合單例模式使用的解決方案。

3. 使用靜態(tài)內(nèi)置類(lèi)實(shí)現(xiàn)單例模式

DCL可以解決多線程單例模式的非線程安全問(wèn)題甩十。當(dāng)然船庇,使用其他的辦法也能達(dá)到同樣的效果。

創(chuàng)建類(lèi)MyObject.java代碼如下:

public class MyObject {

    // 內(nèi)部類(lèi)方式
    private static class MyObjectHandler {
        private static MyObject myObject = new MyObject();
    }

    private MyObject() {
    }

    public static MyObject getInstance() {
        return MyObjectHandler.myObject;
    }

}

創(chuàng)建線程類(lèi)MyThread.java代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println(MyObject.getInstance().hashCode());
    }

}

創(chuàng)建運(yùn)行類(lèi)Run.java代碼如下:

import extthread.MyThread;

public class Run {

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.start();
        t2.start();
        t3.start();

    }

}

程序運(yùn)行后的結(jié)果如下:

531436928
531436928
531436928

4. 序列化與反序列化的單例模式實(shí)現(xiàn)

靜態(tài)內(nèi)置類(lèi)可以達(dá)到線程安全問(wèn)題侣监,但如果遇到序列化對(duì)象時(shí)鸭轮,使用默認(rèn)的方式運(yùn)行得到的結(jié)果還是多例的。

創(chuàng)建MyObject.java代碼如下:

import java.io.ObjectStreamException;
import java.io.Serializable;

public class MyObject implements Serializable {

    private static final long serialVersionUID = 888L;

    // 內(nèi)部類(lèi)方式
    private static class MyObjectHandler {
        private static final MyObject myObject = new MyObject();
    }

    private MyObject() {
    }

    public static MyObject getInstance() {
        return MyObjectHandler.myObject;
    }

    protected Object readResolve() throws ObjectStreamException {
        System.out.println("調(diào)用了readResolve方法橄霉!");
        return MyObjectHandler.myObject;
    }

}

創(chuàng)建業(yè)務(wù)類(lèi)SaveAndRead.java代碼如下:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import test.MyObject;

public class SaveAndRead {

    public static void main(String[] args) {
        try {
            MyObject myObject = MyObject.getInstance();
            FileOutputStream fosRef = new FileOutputStream(new File(
                    "myObjectFile.txt"));
            ObjectOutputStream oosRef = new ObjectOutputStream(fosRef);
            oosRef.writeObject(myObject);
            oosRef.close();
            fosRef.close();
            System.out.println(myObject.hashCode());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            FileInputStream fisRef = new FileInputStream(new File(
                    "myObjectFile.txt"));
            ObjectInputStream iosRef = new ObjectInputStream(fisRef);
            MyObject myObject = (MyObject) iosRef.readObject();
            iosRef.close();
            fisRef.close();
            System.out.println(myObject.hashCode());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

}

程序運(yùn)行后的效果如下:

1836019240
81628611

解決辦法就是在反序列化中使用readResolve()方法窃爷。
去掉如下代碼的注釋?zhuān)?/p>

    protected Object readResolve() throws ObjectStreamException {
        System.out.println("調(diào)用了readResolve方法!");
        return MyObjectHandler.myObject;
    }

程序運(yùn)行后的結(jié)果如下:

1836019240
調(diào)用了readResolve方法姓蜂!
1836019240

5. 使用static代碼塊實(shí)現(xiàn)單例模式

靜態(tài)代碼塊中的代碼在使用類(lèi)的時(shí)候就已經(jīng)執(zhí)行了按厘,所以可以應(yīng)用靜態(tài)代碼塊的這個(gè)特性來(lái)實(shí)現(xiàn)單例設(shè)計(jì)模式。

創(chuàng)建MyObject.java代碼如下:

public class MyObject {

    private static MyObject instance = null;

    private MyObject() {
    }

    static {
        instance = new MyObject();
    }

    public static MyObject getInstance() {
        return instance;
    }

}

創(chuàng)建線程類(lèi)MyThread.java代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(MyObject.getInstance().hashCode());
        }
    }
}

創(chuàng)建運(yùn)行類(lèi)Run.java代碼如下:

import extthread.MyThread;

public class Run {

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.start();
        t2.start();
        t3.start();

    }

}

程序運(yùn)行后的結(jié)果如下:

186668687
186668687
186668687
186668687
186668687
186668687
186668687
186668687
186668687
186668687
186668687
186668687
186668687
186668687
186668687

6. 使用enum枚舉數(shù)據(jù)類(lèi)型實(shí)現(xiàn)單例模式

枚舉enum和靜態(tài)代碼塊的特性相似钱慢,在使用枚舉類(lèi)時(shí)逮京,構(gòu)造方法會(huì)被自動(dòng)調(diào)用,也可以應(yīng)用其這個(gè)特性實(shí)現(xiàn)單例設(shè)計(jì)模式束莫。

創(chuàng)建類(lèi)MyObject.java代碼如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public enum MyObject {
    connectionFactory;

    private Connection connection;

    private MyObject() {
        try {
            System.out.println("調(diào)用了MyObject的構(gòu)造");
            String url = "jdbc:mysql://localhost:3306/test";
            String username = "root";
            String password = "root";
            String driverName = "com.mysql.jdbc.Driver";
            Class.forName(driverName);
            connection = DriverManager.getConnection(url, username, password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public Connection getConnection() {
        return connection;
    }
}

創(chuàng)建線程類(lèi)MyThread.java代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(MyObject.connectionFactory.getConnection()
                    .hashCode());
        }
    }
}

創(chuàng)建運(yùn)行類(lèi)Run.java代碼如下:

import extthread.MyThread;

public class Run {

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.start();
        t2.start();
        t3.start();

    }
}

程序運(yùn)行后的結(jié)果如下:

調(diào)用了MyObject的構(gòu)造
482793510
482793510
482793510
482793510
482793510
482793510
482793510
482793510
482793510
482793510
482793510
482793510
482793510
482793510
482793510

7. 完善使用enum枚舉實(shí)現(xiàn)單例模式

前面一節(jié)將枚舉類(lèi)進(jìn)行暴露懒棉,違反了“職責(zé)單一原則”,在本節(jié)中進(jìn)行完善览绿。

更改類(lèi)MyObject.java代碼如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class MyObject {

    public enum MyEnumSingleton {
        connectionFactory;

        private Connection connection;

        private MyEnumSingleton() {
            try {
                System.out.println("創(chuàng)建MyObject對(duì)象");
                String url = "jdbc:mysql://localhost:3306/test";
                String username = "root";
                String password = "root";
                String driverName = "com.mysql.jdbc.Driver";
                Class.forName(driverName);
                connection = DriverManager.getConnection(url, username,
                        password);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public Connection getConnection() {
            return connection;
        }
    }

    public static Connection getConnection() {
        return MyEnumSingleton.connectionFactory.getConnection();
    }

}

更改MyThread.java類(lèi)代碼如下:

import test.MyObject;

public class MyThread extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(MyObject.getConnection().hashCode());
        }
    }
}

程序運(yùn)行的結(jié)果如下:

創(chuàng)建MyObject對(duì)象
2007882269
2007882269
2007882269
2007882269
2007882269
2007882269
2007882269
2007882269
2007882269
2007882269
2007882269
2007882269
2007882269
2007882269
2007882269
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末策严,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子饿敲,更是在濱河造成了極大的恐慌妻导,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诀蓉,死亡現(xiàn)場(chǎng)離奇詭異栗竖,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)渠啤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)添吗,“玉大人沥曹,你說(shuō)我怎么就攤上這事。” “怎么了妓美?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵僵腺,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我壶栋,道長(zhǎng)辰如,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任贵试,我火速辦了婚禮琉兜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘毙玻。我一直安慰自己豌蟋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布桑滩。 她就那樣靜靜地躺著梧疲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪运准。 梳的紋絲不亂的頭發(fā)上幌氮,一...
    開(kāi)封第一講書(shū)人閱讀 51,698評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音胁澳,去河邊找鬼该互。 笑死,一個(gè)胖子當(dāng)著我的面吹牛听哭,可吹牛的內(nèi)容都是我干的慢洋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼陆盘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼普筹!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起隘马,我...
    開(kāi)封第一講書(shū)人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤太防,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后酸员,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蜒车,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年幔嗦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酿愧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邀泉,死狀恐怖嬉挡,靈堂內(nèi)的尸體忽然破棺而出钝鸽,到底是詐尸還是另有隱情,我是刑警寧澤庞钢,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布拔恰,位于F島的核電站,受9級(jí)特大地震影響基括,放射性物質(zhì)發(fā)生泄漏颜懊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一风皿、第九天 我趴在偏房一處隱蔽的房頂上張望河爹。 院中可真熱鬧,春花似錦揪阶、人聲如沸昌抠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)炊苫。三九已至,卻和暖如春冰沙,著一層夾襖步出監(jiān)牢的瞬間侨艾,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工拓挥, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留唠梨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓侥啤,卻偏偏與公主長(zhǎng)得像当叭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盖灸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

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