設(shè)計(jì)模式——單例設(shè)計(jì)模式

什么是設(shè)計(jì)模式衷快?

是一套被反復(fù)使用宙橱、多數(shù)人知曉的、經(jīng)過(guò)分類的蘸拔、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)师郑。一些開(kāi)發(fā)的套路,用于解決某一些特定場(chǎng)景的思想调窍。

什么是單例設(shè)計(jì)模式宝冕?

是一種最最常見(jiàn)的一種模式,保證整個(gè)程序中只有一個(gè)實(shí)例陨晶,這是最基本的猬仁,真正做到整個(gè)系統(tǒng)中唯一并不容易,通常還要考慮反射破壞先誉、序列化/反序列化湿刽、對(duì)象垃圾回收等問(wèn)題。

參考文章:https://blog.csdn.net/tjiyu/article/details/76572617

單例模式的幾種實(shí)現(xiàn)方式

單例實(shí)現(xiàn)方式1.餓漢式

/**
 * 餓漢式-隨著類的加載會(huì)自動(dòng)new出對(duì)象
 */

public class Singleton {
    private Singleton() {
    }//私有化構(gòu)造器

    private static Singleton mInstance = new Singleton();

    public static Singleton getInstance() {
        return mInstance;
    }

}

餓漢式褐耳,簡(jiǎn)單可用诈闺。這種方式比較常用,它基于JVM的類加載器機(jī)制避免了多線程的同步問(wèn)題铃芦,對(duì)象在類裝載時(shí)就實(shí)例化雅镊,所以稱為餓漢式。
Lazy 初始化:否刃滓;
多線程安全:是仁烹;
優(yōu)點(diǎn):沒(méi)有加鎖,執(zhí)行效率會(huì)提高咧虎。
缺點(diǎn):沒(méi)有Lazy初始化卓缰,可能有時(shí)候不需要使用,浪費(fèi)內(nèi)存砰诵。

單例實(shí)現(xiàn)方式2.懶漢式1

多線程并發(fā)的時(shí)候會(huì)有問(wèn)題征唬,有可能會(huì)存在多個(gè)實(shí)例mInstance

/**
 * 懶漢式1-多線程并發(fā)的時(shí)候會(huì)有問(wèn)題,有可能會(huì)存在多個(gè)實(shí)例mInstance
 */

public class Singleton {
    private Singleton() {
    }//私有化構(gòu)造器

    private static Singleton mInstance;

    public static Singleton getInstance() {
        if (mInstance == null)
            mInstance = new Singleton();
        return mInstance;
    }

}

Lazy 初始化:是茁彭;
多線程安全:否总寒;
能夠在getInstance()時(shí)再創(chuàng)建對(duì)象,所以稱為懶漢式理肺。這種實(shí)現(xiàn)最大的問(wèn)題就是不支持多線程摄闸。因?yàn)闆](méi)有加鎖同步善镰。

單例實(shí)現(xiàn)方式3.懶漢式2

解決多線程并發(fā)問(wèn)題,加一個(gè)同步鎖贪薪,但是又會(huì)出現(xiàn)效率問(wèn)題媳禁,就是每次getInstanc的時(shí)候都會(huì)經(jīng)過(guò)同步鎖的判斷!

/**
 * 懶漢式2-解決多線程并發(fā)問(wèn)題画切,加一個(gè)同步鎖,但是又會(huì)出現(xiàn)效率問(wèn)題囱怕,就是每次getInstanc的時(shí)候都會(huì)經(jīng)過(guò)同步鎖的判斷霍弹!
 */

public class Singleton {
    private Singleton() {
    }//私有化構(gòu)造器

    private static Singleton mInstance;

    public static synchronized Singleton getInstance() {
        if (mInstance == null)
            mInstance = new Singleton();
        return mInstance;
    }

}

Lazy 初始化:是
多線程安全:是
除第一次使用,后面getInstance()不需要同步娃弓;每次同步典格,效率很低。

單例實(shí)現(xiàn)方式4.懶漢式3(DCL)

雙重檢查台丛,只會(huì)執(zhí)行一次同步鎖耍缴。(這種方式其實(shí)還是有問(wèn)題!引出volatile關(guān)鍵字)

/**
 * 懶漢式3-雙重檢查挽霉,只會(huì)執(zhí)行一次同步鎖防嗡。(這種方式其實(shí)還是有問(wèn)題!引出volatile關(guān)鍵字)
 */

public class Singleton {
    private Singleton() {
    }//私有化構(gòu)造器

    private static Singleton mInstance;

    public static Singleton getInstance() {
        if (mInstance == null) {
            synchronized (Singleton.class) {
                if (mInstance == null) {
                    mInstance = new Singleton();
                }
            }
        }
        return mInstance;
    }

}

Lazy 初始化:是侠坎;
多線程安全:是蚁趁;
這種方式采用雙鎖機(jī)制,安全且在多線程情況下能保持高性能实胸。
實(shí)例變量需要加volatile 關(guān)鍵字保證易變可見(jiàn)性他嫡,JDK1.5起才可用,引出下面示例庐完。

單例實(shí)現(xiàn)方式5.懶漢式4

/**
 * 懶漢式4-雙重檢查钢属,只會(huì)執(zhí)行一次同步鎖+volatile關(guān)鍵字
 */

public class Singleton {
    private Singleton() {
    }//私有化構(gòu)造器

    private static volatile Singleton mInstance;

    public static Singleton getInstance() {
        if (mInstance == null) {
            synchronized (Singleton.class) {
                if (mInstance == null) {
                    mInstance = new Singleton();
                }
            }
        }
        return mInstance;
    }

}

volatile關(guān)鍵字講解

volatile關(guān)鍵字作用

public class TestValatileDemo1 {

    private static class MyRunnable implements Runnable {
        private boolean flag = false;

        @Override
        public void run() {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            flag = true;
            System.out.println("flag = " + flag);
        }

        public boolean isFlag() {
            return flag;
        }
    }

    public static void main(String[] args) throws InterruptedException {

        MyRunnable runnable = new MyRunnable();
        new Thread(runnable).start();

        while (true) {
            if (runnable.isFlag()) {
                System.out.println("----------------");
                break;
            }
        }

    }
}

運(yùn)行上述代碼淆党,控制臺(tái)輸出:

flag = true

只有flag= true,沒(méi)有分割線輸出生音,且程序沒(méi)有終止退出宁否。

改動(dòng)1:如果在while(true)語(yǔ)句塊中加入線程休眠:

    public static void main(String[] args) throws InterruptedException {

        MyRunnable runnable = new MyRunnable();
        new Thread(runnable).start();

        while (true) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (runnable.isFlag()) {
                System.out.println("----------------");
                break;
            }
        }

    }

運(yùn)行上述代碼,控制臺(tái)輸出:

flag = true
----------------

Process finished with exit code 0

修改2:去掉上面的線程睡眠缀遍,對(duì)flag變量加入volatile關(guān)鍵字修飾:

    private static class MyRunnable implements Runnable {
        private volatile boolean flag = false;

        @Override
        public void run() {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            flag = true;
            System.out.println("flag = " + flag);
        }

        public boolean isFlag() {
            return flag;
        }
    }

運(yùn)行上述代碼慕匠,控制臺(tái)輸出:

----------------
flag = true

Process finished with exit code 0

小結(jié):

可見(jiàn)性,是指線程之間的可見(jiàn)性域醇,一個(gè)線程修改的狀態(tài)對(duì)另一個(gè)線程是可見(jiàn)的台谊。也就是一個(gè)線程修改的結(jié)果蓉媳。另一個(gè)線程馬上就能看到。比如:用volatile修飾的變量锅铅,就會(huì)具有可見(jiàn)性酪呻。volatile修飾的變量不允許線程內(nèi)部緩存和重排序,即直接修改內(nèi)存盐须。所以對(duì)其他線程是可見(jiàn)的玩荠。但是這里需要注意一個(gè)問(wèn)題,volatile只能讓被他修飾內(nèi)容具有可見(jiàn)性贼邓,但不能保證它具有原子性阶冈。比如 volatile int a = 0;之后有一個(gè)操作 a++塑径;這個(gè)變量a具有可見(jiàn)性女坑,但是a++ 依然是一個(gè)非原子操作,也就是這個(gè)操作同樣存在線程安全問(wèn)題统舀。

Volatile原理

Java語(yǔ)言提供了一種稍弱的同步機(jī)制匆骗,即volatile變量,用來(lái)確保將變量的更新操作通知到其他線程誉简。當(dāng)把變量聲明為volatile類型后碉就,編譯器與運(yùn)行時(shí)都會(huì)注意到這個(gè)變量是共享的,因此不會(huì)將該變量上的操作與其他內(nèi)存操作一起重排序描融。volatile變量不會(huì)被緩存在寄存器或者對(duì)其他處理器不可見(jiàn)的地方铝噩,因此在讀取volatile類型的變量時(shí)總會(huì)返回最新寫(xiě)入的值。

在訪問(wèn)volatile變量時(shí)不會(huì)執(zhí)行加鎖操作窿克,因此也就不會(huì)使執(zhí)行線程阻塞骏庸,因此volatile變量是一種比sychronized關(guān)鍵字更輕量級(jí)的同步機(jī)制。

Volatile原理.png

當(dāng)對(duì)非 volatile 變量進(jìn)行讀寫(xiě)的時(shí)候年叮,每個(gè)線程先從內(nèi)存拷貝變量到CPU緩存中具被。如果計(jì)算機(jī)有多個(gè)CPU,每個(gè)線程可能在不同的CPU上被處理只损,這意味著每個(gè)線程可以拷貝到不同的 CPU cache 中一姿。

而聲明變量是 volatile 的,JVM 保證了每次讀變量都從內(nèi)存中讀跃惫,跳過(guò) CPU cache 這一步叮叹。

當(dāng)一個(gè)變量定義為 volatile 之后,將具備兩種特性:

1.保證此變量對(duì)所有的線程的可見(jiàn)性爆存,這里的“可見(jiàn)性”蛉顽,如本文開(kāi)頭所述,當(dāng)一個(gè)線程修改了這個(gè)變量的值先较,volatile 保證了新值能立即同步到主內(nèi)存携冤,以及每次使用前立即從主內(nèi)存刷新悼粮。但普通變量做不到這點(diǎn),普通變量的值在線程間傳遞均需要通過(guò)主內(nèi)存(詳見(jiàn):Java內(nèi)存模型)來(lái)完成曾棕。

2.禁止指令重排序優(yōu)化扣猫。有volatile修飾的變量,賦值后多執(zhí)行了一個(gè)“l(fā)oad addl $0x0, (%esp)”操作翘地,這個(gè)操作相當(dāng)于一個(gè)內(nèi)存屏障(指令重排序時(shí)不能把后面的指令重排序到內(nèi)存屏障之前的位置)申尤,只有一個(gè)CPU訪問(wèn)內(nèi)存時(shí),并不需要內(nèi)存屏障衙耕;(什么是指令重排序:是指CPU采用了允許將多條指令不按程序規(guī)定的順序分開(kāi)發(fā)送給各相應(yīng)電路單元處理)瀑凝。

volatile 性能:

volatile 的讀性能消耗與普通變量幾乎相同,但是寫(xiě)操作稍慢臭杰,因?yàn)樗枰诒镜卮a中插入許多內(nèi)存屏障指令來(lái)保證處理器不發(fā)生亂序執(zhí)行。

單例實(shí)現(xiàn)方式6.靜態(tài)內(nèi)部類(也是比較常用谚中,保證了線程安全)

/**
 * 單例實(shí)現(xiàn)方式6.靜態(tài)內(nèi)部類(也是比較常用渴杆,保證了線程安全)
 */

public class Singleton {
    private Singleton() {//私有化構(gòu)造器
    }

    public static Singleton getInstance() {
        return SingletonHolder.mInstance;
    }

    public static class SingletonHolder {
        private static volatile Singleton mInstance = new Singleton();
    }
}

Lazy 初始化:是;
多線程安全:是宪塔;
同樣利用了JVM類加載機(jī)制來(lái)保證初始化實(shí)例對(duì)象時(shí)只有一個(gè)線程磁奖,靜態(tài)內(nèi)部類SingletonHolder 類只有第一次調(diào)用 getInstance 方法時(shí),才會(huì)裝載從而實(shí)例化對(duì)象某筐。

單例實(shí)現(xiàn)方式7.容器管理

/**
 * 單例實(shí)現(xiàn)方式7.容器管理
 */

public class Singleton {
    private static Map<String, Object> mSingleMap = new HashMap<>();

    private Singleton() {//私有化構(gòu)造器
    }

    static {
        mSingleMap.put("SingletonInstance", new Singleton());
    }

    public static Object getInstance(String key) {
        return mSingleMap.get(key);
    }
}

Android中的系統(tǒng)服務(wù)中比較常見(jiàn):

final class SystemServiceRegistry {
    private static final String TAG = "SystemServiceRegistry";

    // Service registry information.
    // This information is never changed once static initialization has completed.
    private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();
    private static int sServiceCacheSize;

    // Not instantiable.
    private SystemServiceRegistry() { }

    static {
        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                new CachedServiceFetcher<AccessibilityManager>() {
            @Override
            public AccessibilityManager createService(ContextImpl ctx) {
                return AccessibilityManager.getInstance(ctx);
            }});
        //....省略....
    }
   public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

    /**
     * Gets the name of the system-level service that is represented by the specified class.
     */
    public static String getSystemServiceName(Class<?> serviceClass) {
        return SYSTEM_SERVICE_NAMES.get(serviceClass);
    }

    /**
     * Statically registers a system service with the context.
     * This method must be called during static initialization only.
     */
    private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }
}

單例實(shí)現(xiàn)方式8.單例(《Effective Java》推薦比搭,不常見(jiàn))

/**
 * 單例實(shí)現(xiàn)方式8.枚舉
 */

public enum Singleton {
    //定義一個(gè)枚舉的元素,就代表Singleton實(shí)例
    INSTANCE;

    /*
    **假如還定義有下面的方法南誊,調(diào)用:Singleton.INSTANCE.doSomethingMethod();
    */
    public void doSomethingMethod() {

    }
}

Lazy 初始化:否身诺;
多線程安全:是;
從Java1.5開(kāi)始支持enum特性抄囚;無(wú)償提供序列化機(jī)制霉赡,絕對(duì)防止多次實(shí)例化,即使在面對(duì)復(fù)雜的序列化或者反射攻擊的時(shí)候幔托。
不過(guò)穴亏,用這種方式寫(xiě)不免讓人感覺(jué)生疏,這種實(shí)現(xiàn)方式還沒(méi)有被廣泛采用重挑,但這是實(shí)現(xiàn)單例模式的最佳方法嗓化。

開(kāi)發(fā)中常用的幾種(前提是必須線程安全):

  1. 餓漢式——一般情況下都可以使用,最簡(jiǎn)單谬哀,最近本
  2. 靜態(tài)內(nèi)部類的方式——需要演示加載的時(shí)候使用
  3. 雙重檢查的鎖DCL——面試的時(shí)候會(huì)問(wèn)刺覆,也是比較常見(jiàn)
  4. 枚舉——高安全性的情景下使用

上面8種Java單例模式實(shí)現(xiàn)方式除枚舉方式外,其他的給實(shí)例構(gòu)造函數(shù)protected或private權(quán)限玻粪,依然可以通過(guò)相關(guān)反射方法隅津,改變其權(quán)限诬垂,創(chuàng)建多個(gè)實(shí)例。

public class Test {
 
    public static void main(String args[]) {
     
        Singleton singleton = Singleton.getInstance();
 
       try {
 
            Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
            constructor.setAccessible(true);
            Singleton singletonnew = constructor.newInstance();
            System.out.println(singleton == singletonnew);
 
        } catch (Exception e) {
 
        }     
    }
}

輸出結(jié)果:false

可以給構(gòu)造函數(shù)加上判斷伦仍,限制創(chuàng)建多個(gè)實(shí)例结窘,如下:

private Singleton() {
 
    if (null != Singleton.singleton) {
 
        throw new RuntimeException();
    }
}

單例模式在Android中的應(yīng)用場(chǎng)景——Activity的管理類

Activity的管理類可以統(tǒng)一管理Activity的生命周期和操作Activity方法。如A充蓝、B隧枫、C三個(gè)Activity界面,點(diǎn)擊C界面一個(gè)按鈕直接返回到A界面谓苟,B界面自動(dòng)移除的操作官脓。再如單點(diǎn)登錄,全局Activity都要彈出一個(gè)Dialog提示框的場(chǎng)景涝焙。

方案有:
EventBus(純反射效率低)卑笨、廣播(有延遲)、集合管理仑撞、SingleTask(只適用于部分場(chǎng)景)赤兴。

接下來(lái)我們寫(xiě)一個(gè)Activity管理類來(lái)實(shí)現(xiàn)上面的場(chǎng)景1.

ActivityManager:

public class ActivityManager {
    String TAG = "ActivityManager";
    private static volatile ActivityManager mInstance;
    private Stack<Activity> mActivities;

    private ActivityManager() {
        mActivities = new Stack<>();
    }

    public static ActivityManager getInstance() {
        if (mInstance == null) {
            synchronized (ActivityManager.class) {
                if (mInstance == null) {
                    mInstance = new ActivityManager();
                }
            }
        }
        return mInstance;
    }

    // 添加Activity
    public void attach(Activity activity) {
        Log.d(TAG, "attach " + activity);
        mActivities.add(activity);
    }

    // 移除Activity
    /*public void detach(Activity target) {
        for (Activity activity : mActivities) {
            if (activity == target) {
                Log.d(TAG, "detach " + activity);
                mActivities.remove(target);//todo 一邊循環(huán)一邊移除是有問(wèn)題的
            }
        }
    }*/
    // 移除Activity-修改版
    public void detach(Activity target) {
        int size = mActivities.size();
        for (int i = 0; i < size; i++) {
            Activity activity = mActivities.get(i);
            if (activity == target) {
                mActivities.remove(i);
                i--;
                size--;
            }
        }
    }


    // 根據(jù)Activity關(guān)閉Activity
    /*public void finish(Activity target) {
        for (Activity activity : mActivities) {
            if (activity == target) {
                Log.d(TAG, "detach " + activity);
                mActivities.remove(target);//todo 一邊循環(huán)一邊移除是有問(wèn)題的
                target.finish();
            }
        }
    }*/

    // 根據(jù)Activity關(guān)閉Activity-修改版
    public void finish(Activity target) {
        Log.d(TAG, "finish canonicalName:" + target.getClass().getCanonicalName());
        int size = mActivities.size();
        for (int i = 0; i < size; i++) {
            Activity activity = mActivities.get(i);
            if (activity == target) {
                mActivities.remove(i);
                target.finish();
                i--;
                size--;
            }
        }
    }

    // 根據(jù)Class關(guān)閉Activity
    /*public void finish(Class<? extends Activity> targetClass) {
        Log.d(TAG, "finish canonicalName:" + targetClass.getCanonicalName());
        //com.ivyzh.designpatterndemo.d1_singleton_pattern.activities.BMainActivity
        for (Activity activity : mActivities) {
            if (activity.getClass().getCanonicalName().equals(targetClass.getCanonicalName())) {
                mActivities.remove(activity);//todo 一邊循環(huán)一邊移除是有問(wèn)題的
                activity.finish();
            }
        }
    }*/

    // 根據(jù)Class關(guān)閉Activity-修改版
    public void finish(Class<? extends Activity> targetClass) {
        Log.d(TAG, "finish canonicalName:" + targetClass.getCanonicalName());
        //com.ivyzh.designpatterndemo.d1_singleton_pattern.activities.BMainActivity
        int size = mActivities.size();
        for (int i = 0; i < size; i++) {
            Activity activity = mActivities.get(i);
            if (activity.getClass().getCanonicalName().equals(targetClass.getCanonicalName())) {
                mActivities.remove(activity);
                activity.finish();
                i--;
                size--;
            }
        }
    }

    // 退出整個(gè)應(yīng)用
    public void exitApp() {
        int size = mActivities.size();
        for (int i = 0; i < size; i++) {
            Activity activity = mActivities.get(i);
            Log.d(TAG, "exitApp canonicalName:" + activity.getClass().getCanonicalName());
            mActivities.remove(i);
            activity.finish();
            i--;
            size--;
        }
    }

    // 獲取當(dāng)前的Activity,用于全局彈出Dialog
    public Activity currentActivity() {
        return mActivities.lastElement();
    }
}

BaseActivity:

public abstract class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityManager.getInstance().attach(this);
        setContentView(getContentView());
    }

    protected abstract int getContentView();

    @Override
    protected void onDestroy() {
        ActivityManager.getInstance().detach(this);
        super.onDestroy();
    }
}

A隧哮、B桶良、CMainActivity:

public class AMainActivity extends BaseActivity {


    @Override
    protected int getContentView() {
        return R.layout.activity_amain;
    }

    public void click(View v) {
        Intent intent = new Intent(this, BMainActivity.class);
        startActivity(intent);
    }
}

public class BMainActivity extends BaseActivity {


    @Override
    protected int getContentView() {
        return R.layout.activity_bmain;
    }
    public void click(View v) {
        Intent intent = new Intent(this, CMainActivity.class);
        startActivity(intent);
    }
}
public class CMainActivity extends BaseActivity {
    @Override
    protected int getContentView() {
        return R.layout.activity_cmain;
    }

    public void click(View v) {
        ActivityManager.getInstance().finish(this);
        ActivityManager.getInstance().finish(BMainActivity.class);
    }

    public void exit(View v) {
        ActivityManager.getInstance().exitApp();
    }
}

上面的ActivityManager是一個(gè)單例,具有獲取當(dāng)前Activty沮翔、根據(jù)Activity對(duì)象或者Class刪除Activity陨帆、退出應(yīng)用等功能。

總結(jié):
單例常用實(shí)現(xiàn)方式:

1. 餓漢式——一般情況下都可以使用采蚀,最簡(jiǎn)單疲牵,最近本
2. 靜態(tài)內(nèi)部類的方式——需要演示加載的時(shí)候使用
3. 雙重檢查的鎖DCL——面試的時(shí)候會(huì)問(wèn),也是比較常見(jiàn)
4. 枚舉——高安全性的情景下使用

END.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末搏存,一起剝皮案震驚了整個(gè)濱河市瑰步,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌璧眠,老刑警劉巖缩焦,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異责静,居然都是意外死亡袁滥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門灾螃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)题翻,“玉大人,你說(shuō)我怎么就攤上這事∏对” “怎么了塑荒?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)姜挺。 經(jīng)常有香客問(wèn)我齿税,道長(zhǎng),這世上最難降的妖魔是什么炊豪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任凌箕,我火速辦了婚禮,結(jié)果婚禮上词渤,老公的妹妹穿的比我還像新娘牵舱。我一直安慰自己,他們只是感情好缺虐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布芜壁。 她就那樣靜靜地躺著,像睡著了一般高氮。 火紅的嫁衣襯著肌膚如雪沿盅。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天纫溃,我揣著相機(jī)與錄音,去河邊找鬼韧掩。 笑死紊浩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疗锐。 我是一名探鬼主播坊谁,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼滑臊!你這毒婦竟也來(lái)了口芍?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤雇卷,失蹤者是張志新(化名)和其女友劉穎鬓椭,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體关划,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡小染,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贮折。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片裤翩。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖调榄,靈堂內(nèi)的尸體忽然破棺而出踊赠,到底是詐尸還是另有隱情呵扛,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布筐带,位于F島的核電站今穿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏烫堤。R本人自食惡果不足惜荣赶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸽斟。 院中可真熱鬧拔创,春花似錦、人聲如沸富蓄。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)立倍。三九已至灭红,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間口注,已是汗流浹背变擒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寝志,地道東北人娇斑。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像材部,于是被迫代替她去往敵國(guó)和親毫缆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

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

  • 單例模式在我們工作學(xué)習(xí)和大多數(shù)應(yīng)用中經(jīng)常碰到乐导。如:Windows的任務(wù)管理器(TaskManager)苦丁、Windo...
    請(qǐng)叫我張懂閱讀 626評(píng)論 0 2
  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書(shū)筆記,整理的知識(shí)點(diǎn)物臂,也是為了防止忘記旺拉,尊重勞動(dòng)成果,轉(zhuǎn)載注明出處哦棵磷!如果你也喜歡展蒂,那...
    波波波先森閱讀 11,268評(píng)論 4 56
  • 單例模式(SingletonPattern)一般被認(rèn)為是最簡(jiǎn)單努溃、最易理解的設(shè)計(jì)模式褒链,也因?yàn)樗暮?jiǎn)潔易懂捻爷,是項(xiàng)目中最...
    成熱了閱讀 4,253評(píng)論 4 34
  • 今天是我失業(yè)第二天,說(shuō)到失業(yè)并不是被炒魷魚(yú)而是辭職,辭職的原因就是典型的金牛爆發(fā)許許多多的事情積壓過(guò)后被稻草給壓垮...
    木白召召閱讀 309評(píng)論 0 0
  • 上周一直在學(xué)習(xí)vba 蒲牧,但是效果并不好撇贺,這次理論上是要開(kāi)始自己跑程序了,到應(yīng)該還是差很遠(yuǎn)冰抢,所以松嘶,這周需要更用功一點(diǎn)...
    天劫小雨閱讀 144評(píng)論 0 1