[Java] 单例模式的学习笔记(Java版),
分享于 点击 753 次 点评:219
[Java] 单例模式的学习笔记(Java版),
立即加载的一种模式,使用 static 的属性,在类第一次运行的时候实例化这个类的实例。
public class MyObject {
private static MyObject myObject = new MyObject();
private MyObject() {
}
// 缺点: 不能有其他实例变量
// 因为 getInstance 没有加锁,所以可能会出现多线程同步问题
public static MyObject getInstance() {
return myObject;
}
}
public class MyObject {
private static MyObject myObject;
private MyObject() {
}
// 使用的时候才加载
// 但是这个方法同样没有加锁,所以多线程一样会出现非单例情况
public static MyObject getInstance() {
if (null == myObject)
myObject = new MyObject();
return myObject;
}
}
针对懒汉模式出现多个实例的解决方案:
2.1 使用锁 synchronized
public class MyObject {
private static MyObject myObject;
private MyObject() {
}
public synchronized static MyObject getInstance() {
if (null == myObject)
myObject = new MyObject();
return myObject;
}
}
这种方式虽然可以解决多线程多对象的烦恼,但是却是比较影响程序运行速度的,于是,进一步优化。
2.2 使用 synchronized 同步代码块
public class MyObject {
private static MyObject myObject;
private MyObject() {
}
public static MyObject getInstance() {
synchronized (MyObject.this) {
if (null == myObject)
myObject = new MyObject();
return myObject;
}
}
}
这种和2.1 的基本类似,效率也是比较低的,于是进一步做优化。
2.3 使用 synchronized 同步部分代码块
// 宗旨就是,相互独立的可以分别进行实例化,共享资源一定需要加锁使其变成单例。
public class MyObject {
private static MyObject myObject;
private MyObject() {
}
public static MyObject getInstance() {
if (null == myObject) {
// do somethings
synchronized (MyObject.this) {
myObject = new MyObject();
}
}
return myObject;
}
}
但是这种却不是线程安全的,在多线程下,依然会有可能产生多个实例。
2.4 使用 DCL 双检查锁机制
public class MyObject {
private volatile static MyObject myObject;
private MyObject() {
}
public static MyObject getInstance() {
if (null == myObject) {
// do somethings
synchronized (MyObject.this) {
if (null == myObject) {
myObject = new MyObject();
}
}
}
return myObject;
}
}
public class MyObject {
// 内置类方式
private static class MyObjectHandler {
private static MyObject myObject = new MyObject();
}
private MyObject() {
}
public static MyObject getInstance () {
return MyObjectHandler.myObject;
}
}
// 摘录: 静态内部类是可以达到线程安全问题,但如果遇到序列化对象时,使用默认的方式运行得到的结果还是多例的。
// 如果碰到了序列化 IO 流对象,都是多例的,这是正常的。
4. 序列化与反序列化的单例模式的实现
public class MyObject implements Serializable {
private static final long serialVersionUID = 888L;
// 内置类方式
private static class MyObjectHandler {
private static MyObject myObject = new MyObject();
}
private MyObject() {
}
public static MyObject getInstance () {
return MyObjectHandler.myObject;
}
// TODO: 关于这个方法网上是怎么说的
protected Object readResolve() throws ObjectStreamException {
System.out.println("go into readResolve");
return MyObjectHandler.myObject;
}
}
public class staticNestSingleton {
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) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileInputStream fisRef = new FileInputStream(new File("myObjectFile.txt"));
ObjectInputStream iosRef = new ObjectInputStream(fisRef);
MyObject newObject = (MyObject) iosRef.readObject();
iosRef.close();
fisRef.close();
System.out.println(newObject.hashCode());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public class MyObject {
private static MyObject myObject = null;
private MyObject() {
}
static {
myObject = new MyObject();
}
public static MyObject getInstance () {
return myObject;
}
}
相关文章
- 暂无相关文章
用户点评