java 多线程,单例模式类(创建对象)最优写法

单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
  • 1、单例类只能有一个实例。
  • 2、单例类必须自己创建自己的唯一实例。
  • 3、单例类必须给所有其他对象提供这一实例。
import java.util.HashSet;
import java.util.Set;

/**
 * @ClassName SingleInstance
 * @projectName: object1
 * @author: Zhangmingda
 * @description: 单例模式,多个线程创建这个类的实例,实际只返回同一个对象
 * date: 2021/4/26.
 */
public class SingleInstance {
    /**
     * 用一个私有变量存放自己这个类的对象
     */
    private static SingleInstance singleInstance = null;

    /**
     * 将构造方法私有化,避免被外面的类new出来
     */
    private SingleInstance() {
    }
    /**
     * 提供获取实例的方法
     */
    public static SingleInstance instance(){
        String tName = Thread.currentThread().getName();
//        System.out.println(tName + "获取/创建实例");
        /**
         * 方式1:两层if判断,第一层判断不为null直接返回(快速),第二层加锁再判断一次,保证只有一个线程创建实例,其他线程二次判断不为null直接返回
         */
        if (singleInstance == null){
            /**
             * 同步代码块避免多线程同时运行时,同时运行到此处并发都认为singleInstance == null,导致并发创建实例
             */
            System.out.println( tName+ "判断当前实例为null");
            synchronized (SingleInstance.class){
                if (singleInstance == null){
                    System.out.println(tName + "创建实例");
                    singleInstance = new SingleInstance();
                }
                else {
                    System.out.println(tName + "创建实例前二次判断,发现已有实例");
                }
            }
        }else {System.out.println(tName + "第一次判断,发现已有实例");}

        /**
         * 方式二:所有创建对象的线程进来都串行判断,效率要比方式1低,因为明明有已存在实例,也得等别的线程释放锁才能返回实例
         * 同步代码块避免多线程同时运行时,同时运行到此处并发都认为singleInstance == null,导致并发创建实例
         */
//        synchronized (SingleInstance.class){
//            if (singleInstance == null){
//                System.out.println(tName + "创建实例");
//                singleInstance = new SingleInstance();
//            }else {
//                System.out.println(tName + "获取到已存在实例");
//            }
//        }
        return singleInstance;
    }

    public static void main(String[] args) throws InterruptedException {
        Runnable r = () -> {
            SingleInstance.instance();
        };
        Set<Thread> singleInstances = new HashSet<>();
        for (int i=0; i<10; i++) {
            singleInstances.add(new Thread(r,"t"+i));
        }
        singleInstances.forEach(thread -> thread.start());
        Thread.sleep(1000);
    }
}

 

 

posted on 2021-04-26 12:41  zhangmingda  阅读(470)  评论(0编辑  收藏  举报

导航