记录单例模式遇到多线程时的多种情况

来源:互联网 发布:python ssh 爆破 编辑:程序博客网 时间:2024/05/13 18:26

单例模式有很多种,也有很多人总结了,我这里自己总结多线程与单例模式的情况,这样感觉印象会比较深刻。简单的懒汉饿汉式单例我就不写了。。

(1)DCL双检查锁机制,用来实现多线程环境中的延迟加载单例设计模式。完整的实现代码如下:(运行结果自己可以复制粘贴就可以运行测试了)

package wu;public class MyObject {private static  MyObject instance ;private MyObject (){}public  static MyObject getInstance(){if(instance==null){synchronized(MyObject.class){if(instance==null){instance=new MyObject();}}}return instance;}public static void main(String [] args){MyThread_1 t1=new MyThread_1();MyThread_1 t2=new MyThread_1();t1.start();t2.start();}}class MyThread_1 extends Thread{public void run(){System.out.println(MyObject.getInstance().hashCode());}}

这种情况下可以防止多线程执行时的不安全性(即是利用了第二个instance判断做到)


(2),使用静态内部类实现单例模式,利用静态的东西只会被内存加载一次的特性,完整实现代码如下:

package wu;public class staticTest {private static class MyObject{private static MyObject instance=new MyObject();private MyObject(){}public MyObject getInstance(){return MyObject.instance;}}public static void main(String [] args){MyThread_2 t1=new MyThread_2();MyThread_2 t2=new MyThread_2();t1.start();t2.start();}}class MyThread_2 extends Thread{public void run(){System.out.println(MyObject.getInstance().hashCode());}}

注意:如果是遇到序列化对象的话,静态类这种实现方式还是采用默认的方式,最后还是多实例,而不是单例的!


(3),序列化方式的单例实现:完整代码如下:

package wu;import java.io.ByteArrayInputStream;  import java.io.ByteArrayOutputStream;  import java.io.InputStream;  import java.io.ObjectInputStream;  import java.io.ObjectOutputStream;  import java.io.ObjectStreamException;  import java.io.Serializable;    public class SerializeTest  implements Serializable{   private static final long serialVersionUID = -1734754422962712867L;// 单例  (这里随便写一种单例模式就可以了.)    private  static  SerializeTest instance ;      public static SerializeTest getInstance(){      if(instance==null){    synchronized(SerializeTest.class){    if(instance==null){    instance=new SerializeTest();    }    }    }return instance;      }    private SerializeTest(){      }         //防止单例对象在序列化后生成“多例”     private Object readResolve() throws ObjectStreamException {         return instance;      }           //序列化克隆     public SerializeTest deepCopy() throws Exception{          ByteArrayOutputStream os = new ByteArrayOutputStream();          ObjectOutputStream oos = new ObjectOutputStream(os);          oos.writeObject(SerializeTest.getInstance());                    InputStream is = new ByteArrayInputStream(os.toByteArray());          ObjectInputStream ois = new ObjectInputStream(is);          SerializeTest test = (SerializeTest) ois.readObject();          return test;      }        public static void main(String args[]) {           // 只要打印出的TestSingleton对象地址一致,          // 说明依然是单例对象          //把readResolve方法注释掉的话地址就不一致了!         System.out.println(SerializeTest.getInstance().hashCode());          try {              System.out.println(SerializeTest.getInstance().deepCopy().hashCode());          } catch (Exception e) {              e.printStackTrace();          }      }  }

(4)使用static代码块来实现,代码如下:

package wu;public class staticTest {private static staticTest instance=null;private staticTest(){}static{            instance=new staticTest();}public static staticTest getInstance(){return instance;}public static void main(String [] args){MyThread_2 t1=new MyThread_2();MyThread_2 t2=new MyThread_2();t1.start();t2.start();}}class MyThread_2 extends Thread{public void run(){System.out.println(MyObject.getInstance().hashCode());}}

(5)还有一种enum类型也比较少见,具体代码我就不写了,不过我可以举个例子,也就是数据库连接代码那里可以使用enum方式实现的单例。


大概一些重要也有点偏的方法实现多线程单例模式。


0 0