单例模式
参考《多线程编程核心技术》 高洪岩 1
单例模式分为
- “懒汉模式”/ 延迟加载,
- “饿汉模式”/ 立即加载。
延时加载
传统的,延时加载:
public class MyObject {
private static MyObject myObject;
private MyObject() {
}
public static MyObject getInstance() {
// 延迟加载
if (myObject != null) {
} else {
myObject = new MyObject();
}
return myObject;
}
}
立即加载
public class MyObject {
// 立即加载方式==饿汉模式
private static MyObject myObject = new MyObject();
private MyObject() {
}
public static MyObject getInstance() {
// 此代码版本为立即加载
// ① 此版本代码的缺点是不能有其它实例变量
// ② 因为getInstance()方法没有同步
// 所以有可能出现非线程安全问题
return myObject;
}
}
多线程下单例模式实现
① synchronized关键字
但是效率低
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;
}
}
② DCL锁实现
双重检查Double-Check Locking
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 class MyObject {
// 内部类方式
private static class MyObjectHandler {
private static MyObject myObject = new MyObject();
}
private MyObject() {
}
public static MyObject getInstance() {
return MyObjectHandler.myObject;
}
}
内部类虽然可以解决多线程单例模式问题,但是遇到序列化对象时,得到的还是多例,解决的方法是反序列化中使用readResolve()方法。
④ 序列化与反序列化的单例模式
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 MyObject {
private static MyObject instance = null;
private MyObject() {
}
// 静态代码块
static {
instance = new MyObject();
}
public static MyObject getInstance() {
return instance;
}
}
⑥ 使用enum枚举类型实现单例模式
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class MyObject {
public enum MyEnumSingleton {
connectionFactory;
private Connection connection;
private MyEnumSingleton() {
try {
System.out.println("创建MyObject对象");
String url = "jdbc:sqlserver://localhost:1079;databaseName=y2";
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 static Connection getConnection() {
return MyEnumSingleton.connectionFactory.getConnection();
}
}