Java多线程编程核心技术--第六章

Chapter 6

第六章主要介绍如何使单例模式遇到多线程是安全的、正确的

  • 立即加载/”饿汉式”
/**
 * 立即加载单例模式/”饿汉式“
 * Created by boboan on 2018/6/5.
 */
public class MyObject {
    private static MyObject myObject = new MyObject();

    public MyObject() {
    }
    public static MyObject getInstance(){
        return myObject;
    }
}
  • 延迟加载/”懒汉式”
/**
 * 延迟加载单例模式/"懒汉式"
 * 
 * Created by boboan on 2018/6/5.
 */
public class MyObject2 {
    private static MyObject2 myObject;

    public MyObject2() {
    }
    public static MyObject2 getInstance(){
        if (myObject != null) {

        }else {
            return myObject = new MyObject2();
        }
        return myObject;
    }
}

但是这种方法在多线程的情况是错误的,出现多例的情况

/**
 * 延迟加载单例模式/"懒汉式"
 * 
 * Created by boboan on 2018/6/5.
 */
public class MyObject3 {
    private static MyObject3 myObject;

    public MyObject3() {
    }
    //设置同步方法效率比较低
    //给方法加锁
    synchronized public static MyObject3 getInstance(){
        try {
            if (myObject != null) {

            }else {
                Thread.sleep(3000);
                return myObject = new MyObject3();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }
}

这种方法在多线程是错误的,可以通过加 synchronized 同步来解决

/**
 * 延迟加载单例模式/"懒汉式"
 * 
 * Created by boboan on 2018/6/5.
 */
public class MyObject4 {
    private static MyObject4 myObject;

    public MyObject4() {
    }

    public static MyObject4 getInstance(){
        try {

                if (myObject != null) {

                }else {
                    synchronized (MyObject4.class) {
                        Thread.sleep(3000);
                        return myObject = new MyObject4();
                    }
                }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }
}

synchronized 同步效率低,采用同步代码块,对关键代码同步效率稍微提升,但是多线程下还是无法解决

  • DCL 双检查锁机制(推荐)
/**
 * 延迟加载单例模式/"懒汉式"
 * 
 * Created by boboan on 2018/6/5.
 */
public class MyObject5 {
    private volatile static MyObject5 myObject;

    public MyObject5() {
    }

    public static MyObject5 getInstance(){
        try {

                if (myObject != null) {

                }else {
                        Thread.sleep(3000);
                        synchronized (MyObject5.class) {
                            if (myObject==null) {
                                myObject = new MyObject5();
                            }
                        }
                }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }
}

DCL 双检查锁机制来解决问题,保证了不需要同步代码块的异步执行,又保证了单例的效果

  • 静态内置类实现单例模式(推荐)
/**
 * 静态内置类实现单例模式
 *
 * Created by boboan on 2018/6/5.
 */
public class MyObject6 {
    private static class MyObjectHandler{
        private static MyObject myObject = new MyObject();
    }

    public MyObject6() {
    }

    public static MyObject getInstance(){
        return MyObjectHandler.myObject;
    }
}
  • 序列化与反序列化实现单例模式
**
 * 序列化与反序列化实现单例模式
 * 避免枚举类暴露
 *
 * Created by boboan on 2018/6/5.
 */
public class MyObject10 implements Serializable{
    public static  final  long seriVersionUID = 898L;
    public static class MyObjectHandler{
        private static final MyObject10 myObject10= null;
    }
    private  MyObject10(){

    }
    public  static MyObject10 getInstance(){
        return MyObjectHandler.myObject10;
    }
    protected Object readResolve(){
        System.out.println("调用了 read 方法");
        return MyObjectHandler.myObject10;
    }
}
  • static 代码块实现单例模式
/**
 * static 代码块实现单例模式
 *
 * Created by boboan on 2018/6/5.
 */
public class MyObject7 {
    private static MyObject myObject = null;

    public MyObject7() {
    }

    static {
        myObject = new MyObject();
    }
    public static MyObject getInstance(){
        return myObject;
    }
}

静态代码块在使用类的时候就执行了,利用此特性实现单例

  • enum 枚举数据类型实现单例模式
/**
 * 枚举类实现单例模式
 * 避免枚举类暴露
 *
 * Created by boboan on 2018/6/5.
 */
public class MyObject9 {
    public enum MyenumSingleton{

    connectionFactory;
    private  int tag;
    private MyenumSingleton() {
        System.out.println("调用了");
        tag = 1;
    }
    public int getTag(){
        return tag;
    }
    }
    public static int getComTag(){
        return MyenumSingleton.connectionFactory.getTag();
    }

}

使用枚举类时,构造方法会被自动调用。所以可以用来创建单例

猜你喜欢

转载自blog.csdn.net/ouzhuangzhuang/article/details/80619174