一:饿汉式
public class MyObject { // 立即加载方式==饿汉模式 private static MyObject myObject = new MyObject(); private MyObject() { } public static MyObject getInstance() { // 此代码版本为立即加载 // 此版本代码的缺点是不能有其它实例变量 // 因为getInstance()方法没有同步 // 所以有可能出现非线程安全问题 return myObject; } }
public class MyThread extends Thread { @Override public void run() { System.out.println(MyObject.getInstance().hashCode()); } }
public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); }
多线程获取单例,打印的hashcode是同一个值,说明对象是同一个
二:懒汉式(1)
public class MyObject { private static MyObject myObject; private MyObject() { } // 设置同步方法效率太低了 // 整个方法被上锁 synchronized public static MyObject getInstance() { try { if (myObject != null) { } else { // 模拟在创建对象之前做一些准备性的工作 Thread.sleep(3000); myObject = new MyObject(); } } catch (InterruptedException e) { e.printStackTrace(); } return myObject; } }
public class MyThread extends Thread { @Override public void run() { System.out.println(MyObject.getInstance().hashCode()); } }
public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); }
二:懒汉式(2)
public class MyThread extends Thread { @Override public void run() { System.out.println(MyObject.getInstance().hashCode()); } }
public class MyObject { private volatile static MyObject myObject; private MyObject() { } // 使用双检测机制来解决问题 // 即保证了不需要同步代码的异步 // 又保证了单例的效果 public static MyObject getInstance() { try { if (myObject != null) { } else { // 模拟在创建对象之前做一些准备性的工作 Thread.sleep(3000); synchronized (MyObject.class) { if (myObject == null) { myObject = new MyObject(); } } } } catch (InterruptedException e) { e.printStackTrace(); } return myObject; } // 此版本的代码称为: // 双重检查Double-Check Locking }
public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); }
三:使用静态内置类实现单例模式
public class MyObject { // 内部类方式 private static class MyObjectHandler { private static MyObject myObject = new MyObject(); } private MyObject() { } public static MyObject getInstance() { return MyObjectHandler.myObject; } }
public class MyThread extends Thread { @Override public void run() { System.out.println(MyObject.getInstance().hashCode()); } }
public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); }
四:使用静态代码块实现单例模式
public class MyObject { private static MyObject instance = null; private MyObject() { } static { instance = new MyObject(); } public static MyObject getInstance() { return instance; } }
public class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(MyObject.getInstance().hashCode()); } } }
public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); }
五:使用枚举实现单例模式
public enum MyObject { connectionFactory; private Connection connection; private MyObject() { try { System.out.println("调用了MyObject的构造"); String url = "jdbc:sqlserver://localhost:1079;databaseName=ghydb"; String username = "sa"; String password = ""; 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 class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(MyObject.connectionFactory.getConnection() .hashCode()); } } }
public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); }
六:序列化与反序列化的单例模式实现
public class MyObject implements Serializable { private static final long serialVersionUID = 888L; // 内部类方式 private static class MyObjectHandler { private static final MyObject myObject = new MyObject(); } private MyObject() { } public static MyObject getInstance() { return MyObjectHandler.myObject; } protected Object readResolve() throws ObjectStreamException { System.out.println("调用了readResolve方法!"); return MyObjectHandler.myObject; } }
public class SaveAndRead { public static void main(String[] args) { try { MyObject myObject = MyObject.getInstance(); FileOutputStream fosRef = new FileOutputStream(new File( "myObjectFile.txt")); ObjectOutputStream oosRef = new ObjectOutputStream(fosRef); oosRef.writeObject(myObject); oosRef.close(); fosRef.close(); System.out.println(myObject.hashCode()); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { FileInputStream fisRef = new FileInputStream(new File( "myObjectFile.txt")); ObjectInputStream iosRef = new ObjectInputStream(fisRef); MyObject myObject = (MyObject) iosRef.readObject(); iosRef.close(); fisRef.close(); System.out.println(myObject.hashCode()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }