单例模式

Posted xzshare

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式相关的知识,希望对你有一定的参考价值。

      设计模式大家都很熟悉,今天来记录下最基础也最简单的单例模式

      单例模式分为两类,一是饿汉式,另外就是相对的懒汉式

      想来看看饿汉式

      常见的实现方式如下:

 

 1 public class SingletonHungry {
 2     private static SingletonHungry instance = new SingletonHungry();
 3 
 4     private String token;
 5 
 6     private SingletonHungry() {
 7         token = System.currentTimeMillis() + "";
 8     }
 9 
10     public static SingletonHungry getInstance() {
11         return instance;
12     }
13 
14     public String getToken() {
15         return token;
16     }
17 }

新增token来验证线程安全

来个线程安全的

public class SingletonHungrySafe {

    private static String token;

    //jvm加载时会实例化
    private static class Holder {
        private static SingletonHungrySafe INSTANCE = new SingletonHungrySafe();
    }

    private SingletonHungrySafe() {
        token = System.currentTimeMillis() + "";
    }

    public static final SingletonHungrySafe getInstance() {
        return Holder.INSTANCE;
    }

    public String getToken() {
        return token;
    }
}
可以保证在各个线程获取Holder.INSTANCE变量之前完成。在保证线程安全的同时,又可以延迟实例化,并且没有降低并发性

接下来看看懒汉式,相对的,懒汉式是用时才加载,延后性。
先来个线程不安全的
public class SingletonLazy {
    private static SingletonLazy instance;

    private SingletonLazy() {
    }

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

线程安全的

public class SingletonLazySafe {
    private volatile static SingletonLazySafe instance;

    private SingletonLazySafe() {
    }

    public static SingletonLazySafe getInstance() {
        if (null == instance) {
            synchronized (SingletonLazySafe.class) {
                if (null == instance) {
                    instance = new SingletonLazySafe();
                }
            }
        }
        return instance;
    }
}
双重检查加锁,保证线程安全。

同时,我们可以对这些进行测试
public class SingletonTest {

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 1000; i++) {
            Single single = new Single();
            single.start();
        }
    }

    static class Single extends Thread {

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

    private static void checkSingleHungrySafe() {
        SingletonHungrySafe singletonHungrySafe = SingletonHungrySafe.getInstance();
        System.out.println("Thread id=" + Thread.currentThread().getId() + "token:" + singletonHungrySafe.getToken());
    }

    private static void checkSingleHungry() {
        SingletonHungry singletonHungry = SingletonHungry.getInstance();
        System.out.println("Thread id=" + Thread.currentThread().getId() + "token:" + singletonHungry.getToken());
    }
}

验证线程安全问题

      

以上是关于单例模式的主要内容,如果未能解决你的问题,请参考以下文章

常用代码片段

性能比较好的单例写法

片段作为 Android 中的单例

单例片段或保存网页视图状态

你熟悉的设计模式都有哪些?写出单例模式的实现代码

单例模式以及静态代码块