标签:
前面讲的用DCL可以解决多线程单例模式的非线程安全,虽然看下去十分完美,但还是有一些问题,具体分析看这篇:http://blog.csdn.net/ochangwen/article/details/51348078
当然用其他的办法也能达到同样的效果。
public class Singleton { /* 私有构造方法,防止被实例化 */ private Singleton() { } /* 此处使用一个内部类来维护单例 */ private static class SingletonFactory { private static Singleton instance = new Singleton(); } /* 获取实例 */ public static Singleton getInstance() { return SingletonFactory.instance; } }自定义线程
public class MyThread extends Thread { @Override public void run() { System.out.println(Singleton.getInstance().hashCode()); } }
public class Run { public static void main(String[] args) throws ParseException { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); } }
1756075494 1756075494 1756075494 |
静态内置类可以达到线程安全问题,但如果遇到序列化对象时,使用默认的方式运行得到的结果还是多例的。
public class Singleton implements Serializable{ /* 私有构造方法,防止被实例化 */ private Singleton() { } /* 此处使用一个内部类来维护单例 */ private static class SingletonFactory { private static Singleton instance = new Singleton(); } /* 获取实例 */ public static Singleton getInstance() { return SingletonFactory.instance; } /* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */ protected Object readResolve() throws ObjectStreamException{ System.out.println("调用了readResolve方法"); return getInstance(); } }创建业务类SaveAndRead,代码如下:
public class SaveAndRead { public static void main(String[] args) { try { Singleton singleton = Singleton.getInstance(); FileOutputStream fosRef = new FileOutputStream(new File("mySingletonFIle.txt")); ObjectOutputStream oosRef = new ObjectOutputStream(fosRef); oosRef.writeObject(singleton); oosRef.close(); fosRef.close(); System.out.println(singleton.hashCode()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try{ FileInputStream fisRef = new FileInputStream(new File("mySingletonFIle.txt")); ObjectInputStream iosRef = new ObjectInputStream(fisRef); Singleton singleton = (Singleton) iosRef.readObject(); iosRef.close(); fisRef.close(); System.out.println(singleton.hashCode()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
723635264 调用了readResolve方法 723635264 |
1484511730 588729095 |
----------------------------------------------------------------------------------------------------
静态代码块中的代码在使用类的时候就已经执行了,所以可以应用静态代码块的这个特性来实现单例设计模式。
public class Singleton { /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */ private static Singleton instance = null; /* 私有构造方法,防止被实例化 */ private Singleton() { } static { instance = new Singleton(); } public static Singleton getInstance() { return instance; } }自定义线程MyThread和Run类不变,结果如下:
1032010069 1032010069 1032010069 |
枚举enum和静态代码块的特性相似,在使用枚举类时,构造方法会被自动调用,也可以应用其这个特性实现单例设计模式,最经典的就是数据库连接。
public enum Singleton { connectionFactory; private Connection connection; private Singleton() { try { System.out.print("调用了Singleton的构造!"); String url = "jdbc:sqlserver://localhost:1079;databaseNme=DB"; String username = "123456"; String password = "123456"; String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; Class.forName(driverName); connection = DriverManager.getConnection(url, username,password); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } public Connection getConnection() { return connection; } }自定义线程里的run方法修改为:
public void run() { System.out.println(Singleton.connectionFactory. getConnection().hashCode()); }
1032010069 1032010069 1032010069 |
前面一节将枚举类进行暴露,违反了“职责单一原则”,下面进行完善。
public class Singleton { public enum MySingleton { connectionFactory; private Connection connection; private MySingleton() { try { System.out.print("调用了Singleton的构造!"); String url = "jdbc:sqlserver://localhost:1079;databaseNme=DB"; String username = "123456"; String password = "123456"; String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; Class.forName(driverName); connection = DriverManager.getConnection(url, username,password); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } public Connection getConnection() { return connection; } } public static Connection getConnection() { return MySingleton.connectionFactory.getConnection(); } }
Java多线程编程6--单例模式与多线程--使用静态内置类、(反)序列化、static代码块、enum枚举数据类实现
标签:
原文地址:http://blog.csdn.net/ochangwen/article/details/51351470