美文网首页
Java多线程编程核心技术4——单例模式与多线程

Java多线程编程核心技术4——单例模式与多线程

作者: 有奶喝先森 | 来源:发表于2017-02-17 11:04 被阅读0次

    1.立即加载/饿汉模式

    package singleton;

    public class MyThread extends Thread{
     @Override
     public void run() {
      System.out.println(MyObject.getInstance().hashCode());
     }
    }

    package singleton;

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

    package singleton;

    public class Run {
     public static void main(String[] args) {
      MyThread t1 = new MyThread();
      MyThread t2 = new MyThread();
      MyThread t3 = new MyThread();
      t1.start();
      t2.start();
      t3.start();
     }
    }

    运行结果皆为:

    11077203

    2.延迟加载/懒汉模式

    package singleton;

    public class MyObject2 {
     private static MyObject2 myObject;

     public static MyObject2 getInstance() {
      try {
       if (myObject == null) {
        Thread.sleep(3000);//模拟在创建对象前做一些准备工作
        myObject = new MyObject2();
       }
      } catch (InterruptedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
      return myObject;                  
     }
    }

    在多线程中,就会出现取出多个实例的情况,与单例模式的初衷是相背离的。运行结果为:

    11077203

    14576877

    12677476

    3.懒汉模式的改进方法

    3.1 整个getInstance()方法声明synchronized关键字 ,但是效率太低。

    3.2 在getInstance()方法里声明MyObject.class的synchronized同步语句块,其实相当于全部代码被上锁,效率依旧很低。

    3.3 在某些重要的代码实施同步语句块,

    package singleton;

    public class MyObject3 {
     private static MyObject3 myObject;

     public static MyObject3 getInstance() {
      try {
       if (myObject == null) {
        Thread.sleep(3000);
        synchronized(MyObject3.class){
         myObject = new MyObject3();
        }

       }
      } catch (InterruptedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
      return myObject;                  
     }
    }

    虽然大大提高效率,但是非线程安全,无效

    3.4 使用DCL双检查锁机制 -- 推荐

    package singleton;

    public class MyObject4 {
     private volatile static MyObject4 myObject;

     public static MyObject4 getInstance() {
      try {
       synchronized (MyObject4.class) {
        if (myObject == null) {
         Thread.sleep(3000);
         myObject = new MyObject4();
        }

       }
      } catch (InterruptedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
      return myObject;
     }
    }

    3.5 静态内部类方式

    package singleton;

    public class MyObject5 {
     private static class MyObjectHandler {
      private static MyObject5 myObject = new MyObject5();
     }

     public static MyObject5 getInstance() {
      return MyObjectHandler.myObject;
     }
    }

    3.6 序列化与反序列化解决:在反序列化中使用readResolve()方法(略)。

    3.7 使用static代码块实现:

    package singleton;

    public class MyObject6 {
     private static MyObject6 instance = null;

     static {
      instance = new MyObject6();
     }

     public static MyObject6 getInstance() {
      return instance;
     }
    }

    3.8 使用枚举数据类型enum:

    使用枚举类时,构造方法会被自动调用。(但不要将枚举类进行曝露,应将枚举类包装在一个正常类中,遵守职责单一原则)

    相关文章

      网友评论

          本文标题:Java多线程编程核心技术4——单例模式与多线程

          本文链接:https://www.haomeiwen.com/subject/tzdtwttx.html