首页 > 其他 > 详细

单例模式

时间:2019-02-13 12:10:07      阅读:169      评论:0      收藏:0      [点我收藏+]
/**
 * 懒汉式单例1
 * 事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效
 * 没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton1 实例
 */
public class Singletion1 {
    //第一步先将构造方法私有化
    private Singletion1(){}
    // 然后声明一个静态变量保存单例的引用
    private static Singletion1 singletion1 = null;
    //通过提供一个静态方法来获得单例的引用
    public static Singletion1 getInstance(){
        if (singletion1==null){
            singletion1 = new Singletion1();
        }
        return singletion1;
    }
}

 

/**
 *懒汉式单例.保证线程安全
 *
 */
public class Singletion2 {
    private Singletion2() {}

    private static Singletion2 singleton2 = null;

    //为了保证多线程环境下正确访问,给方法加上同步锁synchronized
    //虽然线程安全了,但是每次都要同步,会影响性能
//    public static synchronized Singletion2 getInstance(){
//        if (singleton2==null){
//            singleton2 = new Singletion2();
//        }
//        return singleton2;
//    }


    //为了保证多线程环境下的另一种实现方式,双重锁检查
    //做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗
    public static Singletion2 getInstance(){
        if (singleton2 ==null){
            synchronized (Singletion2.class){
                if (singleton2==null){
                    singleton2 = new Singletion2();
                }
            }
        }
        return singleton2;
    }
}

 

/**
 *线程安全问题
 */
public class Singletion2Test {
    String name = null;

    private Singletion2Test(){}

    //volatile关键字来声明单例对象
    //方便编写多线程程序和利于编译器进行优化
    private static volatile Singletion2Test  singletion2Test = null;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public void printInfo(){
        System.out.println(name);
    }
    public static void main(String[] args){
        Singletion2Test instance = Singletion2Test.getInstance();
        instance.setName("abc");
        Singletion2Test instance2 = Singletion2Test.getInstance();
        instance.setName("def");

        instance.printInfo();
        instance2.printInfo();
        System.out.println(instance==instance2);
    }
}

 

/**
 * 懒汉式
 * Singleton4 类被装载了,INSTANCE不一定被初始化
 *只有显示通过调用getInstance方法时,才会显示装载LazyHolder 类
 * 既实现了线程安全,又避免了同步带来的性能影响
 * 利用了classloader的机制来保证初始化instance时只有一个线程
 */
public class Singletion3 {
    // 先声明一个静态内部类
    private static class LazyHolder{
        private static final Singletion3 INSTANCE = new Singletion3();
    }

    private Singletion3(){}

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

}

 

/**
 *饿汉式单例
 * 在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的
 */
public class Singletion4 {
    private Singletion4(){}

    //声明静态变量,在类实例化之前就初始化变量,将对象引用保存
    private static final Singletion4 SINGLETION = new Singletion4();

    public static Singletion4 getInstance(){
        return SINGLETION;
    }
}

 

/**
 * 饿汉式
 * 枚举式单例
 *不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
 */

public class Singletion5 {
    private Singletion5(){}
    public static Singletion5 getInstance(){
        return Singletion.Instance.getInstance();
    }
    private enum Singletion{
        Instance;
        private Singletion5 singletion5;
        private Singletion(){
            singletion5 = new Singletion5();
        }
        public Singletion5 getInstance(){
            return singletion5;
        }
    }
    public static void main(String[] args){
        Singletion5 instance1 = Singletion5.getInstance();
        Singletion5 instance2 = Singletion5.getInstance();
        System.out.println(instance1==instance2);
    }
}

 

import java.util.HashMap;
import java.util.Map;

/**
 *登记式单例
 * 内部实现还是用的饿汉式单例,因为其中的static方法块,它的单例在类被装载的时候就被实例化了
 * 维护了一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从Map直接返回,对于没有登记的,则先登记,然后返回
 */
public class Singletion6 {
    private static Map<String,Singletion6> map = new HashMap<>();

    static {
        Singletion6 singletion6 = new Singletion6();
        map.put(singletion6.getClass().getName(),singletion6);
    }
    protected Singletion6(){}

    public static Singletion6 getInstance(String name){
        if (name==null){
            name = Singletion6.class.getName();
        }
        if (map.get(name)==null){
            try {
                map.put(name, (Singletion6) Class.forName(name).newInstance());
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return map.get(name);
    }
}

 

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;

/**
 *CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行
 *
 * 与CountDownLatch的第一次交互是主线程等待其他线程。主线程必须在启动其他线程后立即调用CountDownLatch.await()方法。这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
 *
 * 其他N 个线程必须引用闭锁对象,因为他们需要通知CountDownLatch对象,
 * 他们已经完成了各自的任务。这种通知机制是通过 CountDownLatch.countDown()方法来完成的;
 * 每调用一次这个方法,在构造函数中初始化的count值就减1。所以当N个线程都调 用了这个方法,count的值等于0,
 * 然后主线程就能通过await()方法,恢复执行自己的任务。
 */
public class Test {
    public static void main(String[] args){
        CountDownLatch latch = new CountDownLatch(100);
        Set<Singletion3> synchronizedSet = Collections.synchronizedSet(new HashSet<>());
        for (int a=0;a<100;a++){
            new Thread(){
                @Override
                public void run() {
                    synchronizedSet.add(Singletion3.getInstance());
                }
            }.start();
            latch.countDown();
        }

        try {
            latch.await();//等待所有线程全部完成,最终输出结果
            System.out.println(synchronizedSet.size());//1
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

 

单例模式

原文:https://www.cnblogs.com/fly-book/p/10369046.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!