史上最全單例模式的寫法以及破壞單例方式

天跟大家講一個(gè)老生常談的話題,單例模式是最常用到的設(shè)計(jì)模式之一腹暖,熟悉設(shè)計(jì)模式的朋友對(duì)單例模式都不會(huì)陌生。網(wǎng)上的文章也很多翰萨,但是參差不齊微服,良莠不齊,要么說(shuō)的不到點(diǎn)子上缨历,要么寫的不完整,我試圖寫一篇史上最全單例模式糙麦,讓你看一篇文章就夠了辛孵。

單例模式定義及應(yīng)用場(chǎng)景

單例模式是指確保一個(gè)類在任何情況下都絕對(duì)只有一個(gè)實(shí)例,并提供一個(gè)全局訪問(wèn)點(diǎn)赡磅。單例模式是創(chuàng)建型模式魄缚。許多時(shí)候整個(gè)系統(tǒng)只需要擁有一個(gè)全局對(duì)象,這樣有利于我們協(xié)調(diào)系統(tǒng)整體的行為焚廊。

比如在某個(gè)服務(wù)器程序中冶匹,該服務(wù)器的配置信息存放在一個(gè)文件中,這些配置數(shù)據(jù)由一個(gè)單例對(duì)象統(tǒng)一讀取咆瘟,然后服務(wù)進(jìn)程中的其他對(duì)象再通過(guò)這個(gè)單例對(duì)象獲取這些配置信息嚼隘。這種方式簡(jiǎn)化了在復(fù)雜環(huán)境下的配置管理。

我們寫單例的思路是袒餐,隱藏其所有構(gòu)造方法飞蛹,提供一個(gè)全局訪問(wèn)點(diǎn)谤狡。

1、餓漢式

這個(gè)很簡(jiǎn)單卧檐,小伙們都寫過(guò)墓懂,這個(gè)在類加載的時(shí)候就立即初始化,因?yàn)樗莛I嘛霉囚,一開始就給你創(chuàng)建一個(gè)對(duì)象捕仔,這個(gè)是絕對(duì)線程安全的,在線程還沒出現(xiàn)以前就實(shí)例化了盈罐,不可能存在訪問(wèn)安全問(wèn)題榜跌。他的缺點(diǎn)是如果不用,用不著暖呕,我都占著空間斜做,造成內(nèi)存浪費(fèi)。

public class HungrySingleton {

    private static final HungrySingleton hungrySingleton = new HungrySingleton();

    private HungrySingleton() {
    }

    public static HungrySingleton getInstance() {
        return hungrySingleton;
    }
}

還有一種是餓漢式的變種湾揽,靜態(tài)代碼塊寫法瓤逼,原理也是一樣,只要是靜態(tài)的库物,在類加載的時(shí)候就已經(jīng)成功初始化了霸旗,這個(gè)和上面的比起來(lái)沒什么區(qū)別,無(wú)非就是裝個(gè)b戚揭,看起來(lái)比上面那種吊诱告,因?yàn)橐娺^(guò)的人不多嘛。

public class HungryStaticSingleton {

    private static final HungryStaticSingleton hungrySingleton;

    static {
        hungrySingleton = new HungryStaticSingleton();
    }

    private HungryStaticSingleton() {
    }

    public static HungryStaticSingleton getInstance() {
        return hungrySingleton;
    }

}

2民晒、懶漢式

簡(jiǎn)單懶漢

為了解決餓漢式占著茅坑不拉屎的問(wèn)題精居,就產(chǎn)生了下面這種簡(jiǎn)單懶漢式的寫法,一開始我先申明個(gè)對(duì)象潜必,但是先不創(chuàng)建他靴姿,當(dāng)用到的時(shí)候判斷一下是否為空,如果為空我就創(chuàng)建一個(gè)對(duì)象返回磁滚,如果不為空則直接返回佛吓。

為什么叫懶漢式,就是因?yàn)樗軕邪〈谷粒扔玫降臅r(shí)候才去創(chuàng)建维雇,看上去很ok,但是在多線程的情況下會(huì)產(chǎn)生線程安全問(wèn)題晒他。

public class LazySimpleSingleton {

    private static LazySimpleSingleton instance;

    private LazySimpleSingleton() {
    }

    public static LazySimpleSingleton getInstance() {
        if (instance == null) {
            instance = new LazySimpleSingleton();
        }
        return instance;
    }

}

如果有兩個(gè)線程同時(shí)執(zhí)行到 if (instance==null) 這行代碼吱型,這是判斷都會(huì)通過(guò),然后各自會(huì)執(zhí)行instance = new Singleton()陨仅,并各自返回一個(gè)instance唁影,這時(shí)候就產(chǎn)生了多個(gè)實(shí)例耕陷,就沒有保證單例,如下圖所示据沈。

怎么解決這個(gè)問(wèn)題呢哟沫,很簡(jiǎn)單,加鎖啊锌介,加一下synchronized即可嗜诀,這樣就能保住線程安全問(wèn)題了。

3孔祸、雙重校驗(yàn)鎖(DCL)

上面這樣寫法帶來(lái)一個(gè)缺點(diǎn)隆敢,就是性能低,只有在第一次進(jìn)行初始化的時(shí)候才需要進(jìn)行并發(fā)控制崔慧,而后面進(jìn)來(lái)的請(qǐng)求不需要在控制了拂蝎,現(xiàn)在synchronized加在方法上,我管你生成沒成生成惶室,只要來(lái)了就得給我排隊(duì)温自,所以這種性能是極其低下的,那怎么辦呢皇钞?

我們知道悼泌,其實(shí)synchronized除了加在方法上,還可以加在代碼塊上夹界,只要對(duì)生成對(duì)象的那一部分代碼加鎖就可以了馆里,由此產(chǎn)生一種新的寫法,叫做雙重檢驗(yàn)鎖可柿,我們看下面代碼鸠踪。

我們看19行將synchronized包在了代碼塊上,當(dāng) singleton == null 的時(shí)候复斥,我們只對(duì)創(chuàng)建對(duì)象這一塊邏輯進(jìn)行了加鎖控制营密,如果 singleton != null 的話,就直接返回永票,大大提升了效率。

在21行的時(shí)候又加了一個(gè)singleton == null滥沫,這又是為什么呢侣集,原因是如果兩個(gè)線程都到了18行,發(fā)現(xiàn)是空的兰绣,然后都進(jìn)入到代碼塊世分,這里雖然加了synchronized,但作用只是進(jìn)行one by one串行化缀辩,第一個(gè)線程往下走創(chuàng)建了對(duì)象臭埋,第二個(gè)線程等待第一個(gè)線程執(zhí)行完畢后踪央,我也往下走,于是乎又創(chuàng)建了一個(gè)對(duì)象瓢阴,那還是沒控制住單例畅蹂,所以在21行當(dāng)?shù)诙€(gè)線程往下走的時(shí)候在判斷一次,是不是被別的線程已經(jīng)創(chuàng)建過(guò)了荣恐,這個(gè)就是雙重校驗(yàn)鎖液斜,進(jìn)行了兩次非空判斷。

我們看到在11行的時(shí)候加了 volatile 關(guān)鍵字叠穆,這是用來(lái)防止指令重排的少漆,當(dāng)我們創(chuàng)建對(duì)象的時(shí)候會(huì)經(jīng)過(guò)下面幾個(gè)步驟,但是這幾個(gè)步驟不是原子的硼被,計(jì)算機(jī)比較聰明示损,有時(shí)候?yàn)榱颂岣咝仕皇前错樞?234執(zhí)行的,可能是3214執(zhí)行嚷硫。

這時(shí)候如果第一個(gè)線程執(zhí)行了instance = new LazyDoubleCheckSingleton()检访,由于指令重排先進(jìn)行了第三步,先分配了一個(gè)內(nèi)存地址论巍,第二個(gè)線程進(jìn)來(lái)的時(shí)候發(fā)現(xiàn)對(duì)象已經(jīng)是非null烛谊,直接返回,但這時(shí)候?qū)ο筮€沒初始化好啊嘉汰,第二個(gè)線程拿到的是一個(gè)沒有初始化好的對(duì)象丹禀!這個(gè)就是要加volatile的原因。

  • 分配內(nèi)存給這個(gè)對(duì)象
  • 初始化對(duì)象
  • 設(shè)置instance指向剛分配的內(nèi)存地址
  • 初次訪問(wèn)對(duì)象

最后說(shuō)下雙重校驗(yàn)鎖鞋怀,雖然提高了性能双泪,但是在我看來(lái)不夠優(yōu)雅,折騰來(lái)折騰去密似,一會(huì)防這一會(huì)防那焙矛,尤其是對(duì)新手不友好,新手會(huì)不明白為什么要這么寫残腌。

4村斟、靜態(tài)內(nèi)部類

上面已經(jīng)將鎖的粒度縮小到創(chuàng)建對(duì)象的時(shí)候了,但不管加在方法上還是加在代碼塊上抛猫,終究還是用到了鎖蟆盹,只要用到鎖就會(huì)產(chǎn)生性能問(wèn)題,那有沒有不用鎖的方式呢闺金?

答案是有的逾滥,那就是靜態(tài)內(nèi)部類的方式,他其實(shí)是利用了java代碼的一種特性败匹,靜態(tài)內(nèi)部類在主類加載的時(shí)候是不會(huì)被加載的寨昙,只有當(dāng)調(diào)用getInstance()方法的時(shí)候才會(huì)被加載進(jìn)來(lái)進(jìn)行初始化讥巡,代碼如下

/**
 * @author jack xu
 * 兼顧餓漢式的內(nèi)存浪費(fèi),也兼顧synchronized性能問(wèn)題
 */
public class LazyInnerClassSingleton {

    private LazyInnerClassSingleton() {
    }

    public static final LazyInnerClassSingleton getInstance() {
        return LazyHolder.INSTANCE;
    }

    private static class LazyHolder {
        private static final LazyInnerClassSingleton INSTANCE = new LazyInnerClassSingleton();
    }

}

好舔哪,講到這里我已經(jīng)介紹了五種單例的寫法欢顷,經(jīng)過(guò)層層的演進(jìn)推理,到第五種的時(shí)候已經(jīng)是很完美的寫法了尸红,既兼顧餓漢式的內(nèi)存浪費(fèi)吱涉,也兼顧synchronized性能問(wèn)題。

那他真的一定完美嗎外里,其實(shí)不然怎爵,他還有一個(gè)安全的問(wèn)題,接下來(lái)我們講下單例的破壞盅蝗,有兩種方式反射和序列化鳖链。

單例的破壞

1、反射

我們知道在上面單例的寫法中墩莫,在構(gòu)造方法上加上private關(guān)鍵字修飾芙委,就是為了不讓外部通過(guò)new的方式來(lái)創(chuàng)建對(duì)象,但還有一種暴力的方法狂秦,我就是不走尋常路灌侣,你不讓我new是吧,我反射給你創(chuàng)建出來(lái)裂问,代碼如下

/**
 * @author jack xu
 */
public class ReflectDestroyTest {

    public static void main(String[] args) {
        try {
            Class<?> clazz = LazyInnerClassSingleton.class;
            Constructor c = clazz.getDeclaredConstructor(null);
            c.setAccessible(true);
            Object o1 = c.newInstance();
            Object o2 = c.newInstance();
            System.out.println(o1 == o2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

上面c.setAccessible(true)就是強(qiáng)吻侧啼,你private了,我現(xiàn)在把你的權(quán)限設(shè)為true堪簿,我照樣能夠訪問(wèn)痊乾,通過(guò)c.newInstance()調(diào)用了兩次構(gòu)造方法,相當(dāng)于new了兩次椭更,我們知道 == 比的是地址哪审,最后結(jié)果是false,確實(shí)是創(chuàng)建了兩個(gè)對(duì)象虑瀑,反射破壞單例成功湿滓。

file

那么如何防止反射呢,很簡(jiǎn)單舌狗,就是在構(gòu)造方法中加一個(gè)判斷

public class LazyInnerClassSingleton {

    private LazyInnerClassSingleton() {
        if (LazyHolder.INSTANCE != null) {
            throw new RuntimeException("不要試圖用反射破壞單例模式");
        }
    }

    public static final LazyInnerClassSingleton getInstance() {
        return LazyHolder.INSTANCE;
    }

    private static class LazyHolder {
        private static final LazyInnerClassSingleton INSTANCE = new LazyInnerClassSingleton();
    }
}

在看結(jié)果叽奥,防止反射成功,當(dāng)調(diào)用構(gòu)造方法時(shí)把夸,發(fā)現(xiàn)單例實(shí)例對(duì)象已經(jīng)不為空了而线,拋出異常铭污,不讓你在繼續(xù)創(chuàng)建了恋日。

file

2膀篮、序列化

接下來(lái)介紹單例的另一種破壞方式,先在靜態(tài)內(nèi)部類上實(shí)現(xiàn)Serializable接口岂膳,然后寫個(gè)測(cè)試方法測(cè)試下誓竿,先創(chuàng)建一個(gè)對(duì)象,然后把這個(gè)對(duì)象先序列化谈截,然后在反序列化出來(lái)筷屡,然后對(duì)比一下

    public static void main(String[] args) {

        LazyInnerClassSingleton s1 = null;
        LazyInnerClassSingleton s2 = LazyInnerClassSingleton.getInstance();

        FileOutputStream fos = null;
        try {

            fos = new FileOutputStream("SeriableSingleton.obj");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(s2);
            oos.flush();
            oos.close();

            FileInputStream fis = new FileInputStream("SeriableSingleton.obj");
            ObjectInputStream ois = new ObjectInputStream(fis);
            s1 = (LazyInnerClassSingleton) ois.readObject();
            ois.close();

            System.out.println(s1);
            System.out.println(s2);
            System.out.println(s1 == s2);

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

我們來(lái)看結(jié)果發(fā)現(xiàn)是false,在進(jìn)行反序列化時(shí)簸喂,在ObjectInputStream的readObject生成對(duì)象的過(guò)程中毙死,其實(shí)會(huì)通過(guò)反射的方式調(diào)用無(wú)參構(gòu)造方法新建一個(gè)對(duì)象,所以反序列化后的對(duì)象和手動(dòng)創(chuàng)建的對(duì)象是不一致的喻鳄。

file

那么怎么避免呢扼倘,依然很簡(jiǎn)單,在靜態(tài)內(nèi)部類里加一個(gè)readResolve方法即可

    private Object readResolve() {
        return LazyHolder.INSTANCE;
    }

在看結(jié)果就變成true了除呵,為什么加了一個(gè)方法就可以避免被序列化破壞呢再菊,這里不在展開,感興趣的小伙伴可以看下ObjectInputStream的readObject()方法颜曾,一步步往下走纠拔,會(huì)發(fā)現(xiàn)最終會(huì)調(diào)用readResolve()方法。

file

至此泛豪,史上最牛b單例產(chǎn)生稠诲,已經(jīng)無(wú)懈可擊、無(wú)可挑剔了候址。

3吕粹、枚舉

那么這里我為什么還要在介紹枚舉呢,在《Effective Java》中岗仑,枚舉是被推薦的一種方式匹耕,因?yàn)樗銐蚝?jiǎn)單,線程安全荠雕,也不會(huì)被反射和序列化破壞稳其。

大家看下才寥寥幾句話,不像上面雖然已經(jīng)實(shí)現(xiàn)了最牛b的寫法炸卑,但是其中的過(guò)程很讓人煩惱啊既鞠,要考慮性能、內(nèi)存盖文、線程安全嘱蛋、破壞啊,一會(huì)這里加代碼一會(huì)那里加代碼,才能達(dá)到最終的效果洒敏。

而使用枚舉龄恋,感興趣的小伙伴可以反編譯看下,枚舉的底層其實(shí)還是一個(gè)class類凶伙,而我們考慮的這些問(wèn)題JDK源碼其實(shí)幫我們都已經(jīng)實(shí)現(xiàn)好了郭毕,所以在 java 層面我們只需要用三句話就能搞定!

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}  

至此函荣,我通過(guò)層層演進(jìn)显押,由淺入深的給大家介紹了單例的這么多寫法,從不完美到完美傻挂,這么多也是網(wǎng)上很常見的寫法乘碑,下面我在送大家兩個(gè)彩蛋,擴(kuò)展一下其他寫單例的方式方法金拒。

彩蛋

1蝉仇、容器式單例

容器式單例是我們 spring 中管理單例的模式,我們平時(shí)在項(xiàng)目中會(huì)創(chuàng)建很多的Bean殖蚕,當(dāng)項(xiàng)目啟動(dòng)的時(shí)候spring會(huì)給我們管理轿衔,幫我們加載到容器中,他的思路方式方法如下睦疫。

public class ContainerSingleton {
    private ContainerSingleton() {
    }

    private static Map<String, Object> ioc = new ConcurrentHashMap<String, Object>();

    public static Object getInstance(String className) {
        Object instance = null;
        if (!ioc.containsKey(className)) {
            try {
                instance = Class.forName(className).newInstance();
                ioc.put(className, instance);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return instance;
        } else {
            return ioc.get(className);
        }
    }
}

這個(gè)可以說(shuō)是一個(gè)簡(jiǎn)易版的 spring 管理容器害驹,大家看下這里用一個(gè)map來(lái)保存對(duì)象,當(dāng)對(duì)象存在的時(shí)候直接從map里取出來(lái)返回出去蛤育,如果不存在先用反射創(chuàng)建一個(gè)對(duì)象出來(lái)宛官,先保存到map中然后在返回出去。我們來(lái)測(cè)試一下瓦糕,先創(chuàng)建一個(gè)Pojo對(duì)象底洗,然后兩次從容器中去取出來(lái),比較一下咕娄,發(fā)現(xiàn)結(jié)果是true亥揖,證明兩次取出的對(duì)象是同一個(gè)對(duì)象。

file

但是這里有一個(gè)問(wèn)題圣勒,這樣的寫法是線程不安全的费变,那么如何做到線程安全呢,這個(gè)留給小伙伴自行獨(dú)立思考完成圣贸。

2挚歧、CAS單例

從一道面試題開始:不使用synchronized和lock,如何實(shí)現(xiàn)一個(gè)線程安全的單例吁峻?我們知道滑负,上面講過(guò)的所有方式中在张,只要是線程安全的,其實(shí)都直接或者間接用到了synchronized矮慕,間接用到是什么意思呢瞧掺,就比如餓漢式、靜態(tài)內(nèi)部類凡傅、枚舉,其實(shí)現(xiàn)原理都是利用借助了類加載的時(shí)候初始化單例肠缔,即借助了ClassLoader的線程安全機(jī)制夏跷。

所謂ClassLoader的線程安全機(jī)制,就是ClassLoader的loadClass方法在加載類的時(shí)候使用了synchronized關(guān)鍵字明未。也正是因?yàn)檫@樣槽华, 除非被重寫,這個(gè)方法默認(rèn)在整個(gè)裝載過(guò)程中都是同步的趟妥,也就是保證了線程安全猫态。

那么答案是什么呢,就是利用CAS樂(lè)觀鎖披摄,他雖然名字中有個(gè)鎖字亲雪,但其實(shí)是無(wú)鎖化技術(shù),當(dāng)多個(gè)線程嘗試使用CAS同時(shí)更新同一個(gè)變量時(shí)疚膊,只有其中一個(gè)線程能更新變量的值义辕,而其它線程都失敗,失敗的線程并不會(huì)被掛起寓盗,而是被告知這次競(jìng)爭(zhēng)中失敗灌砖,并可以再次嘗試,代碼如下:

/**
 * @author jack xu
 */
public class CASSingleton {
    private static final AtomicReference<CASSingleton> INSTANCE = new AtomicReference<CASSingleton>();

    private CASSingleton() {
    }

    public static CASSingleton getInstance() {
        for (; ; ) {
            CASSingleton singleton = INSTANCE.get();
            if (null != singleton) {
                return singleton;
            }

            singleton = new CASSingleton();
            if (INSTANCE.compareAndSet(null, singleton)) {
                return singleton;
            }
        }
    }
}

在JDK1.5中新增的JUC包就是建立在CAS之上的傀蚌,相對(duì)于對(duì)于synchronized這種阻塞算法智末,CAS是非阻塞算法的一種常見實(shí)現(xiàn)爽航,他是一種基于忙等待的算法,依賴底層硬件的實(shí)現(xiàn),相對(duì)于鎖它沒有線程切換和阻塞的額外消耗爷狈,可以支持較大的并行度。

雖然CAS沒有用到鎖缴饭,但是他在不停的自旋奥帘,會(huì)對(duì)CPU造成較大的執(zhí)行開銷,在生產(chǎn)中我們不建議使用舅桩,那么為什么我還會(huì)講呢酱虎,因?yàn)檫@是工作擰螺絲,面試造火箭的典型擂涛!你可以不用读串,但是你得知道聊记,你說(shuō)是吧。

作者:jack_xu

鏈接:https://juejin.im/post/5ed5c50af265da76d3187b30

文源網(wǎng)絡(luò)恢暖,僅供學(xué)習(xí)之用排监,如有侵權(quán)請(qǐng)聯(lián)系刪除。

我將面試題和答案都整理成了PDF文檔杰捂,還有一套學(xué)習(xí)資料舆床,涵蓋Java虛擬機(jī)、spring框架嫁佳、Java線程挨队、數(shù)據(jù)結(jié)構(gòu)、設(shè)計(jì)模式等等蒿往,但不僅限于此盛垦。

關(guān)注公眾號(hào)【java圈子】獲取資料,還有優(yōu)質(zhì)文章每日送達(dá)瓤漏。

file
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腾夯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蔬充,更是在濱河造成了極大的恐慌蝶俱,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饥漫,死亡現(xiàn)場(chǎng)離奇詭異跷乐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)趾浅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門愕提,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人皿哨,你說(shuō)我怎么就攤上這事浅侨。” “怎么了证膨?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵如输,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我央勒,道長(zhǎng)不见,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任崔步,我火速辦了婚禮稳吮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘井濒。我一直安慰自己灶似,他們只是感情好列林,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酪惭,像睡著了一般希痴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上春感,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天砌创,我揣著相機(jī)與錄音,去河邊找鬼鲫懒。 笑死嫩实,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的刀疙。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼扫倡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼谦秧!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起撵溃,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤疚鲤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后缘挑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體集歇,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年语淘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诲宇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惶翻,死狀恐怖姑蓝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吕粗,我是刑警寧澤纺荧,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站颅筋,受9級(jí)特大地震影響宙暇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜议泵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一占贫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧先口,春花似錦靶剑、人聲如沸蜻拨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)缎讼。三九已至,卻和暖如春坑匠,著一層夾襖步出監(jiān)牢的瞬間血崭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工厘灼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留夹纫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓设凹,卻偏偏與公主長(zhǎng)得像舰讹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子闪朱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348