3.使用静态内置类实现单例模式
DCL可以解决多线程单例模式的非线程安全问题。当然,使用其他的办法也能达到同样的效果。
创建项目,名称为6.3,创建类MyObject.java代码如下:
public class MyObject {
//内部类方式
private static class MyObjectHandler {
private static MyObject myObject = new MyObject();
}
private MyObject() {
}
public static MyObject getInstance() {
return MyObjectHandler.myObject;
}
}
创建线程类MyThread.java代码如下:
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
创建运行类Run.java代码如下:
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
运行结果如下所示:
48762339
48762339
48762339
4.序列化与反序列化的单例模式实现
静态内置类可以达到线程安全问题,但如果遇到序列化对象时,使用默认的方式运行得到的结果还是多例的。
创建项目,名称为6.4,创建类MyObject.java代码如下:
import java.io.ObjectStreamException;
import java.io.Serializable;
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;
// }
}
创建业务类SaveAndRead.java代码如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
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();
}
}
}
运行结果如下所示:
2133927002
1607521710
不是同一个对象
解决办法就是在反序列化中使用readResolve()方法。
去掉如下代码的注释:
protected Object readResolve() throws ObjectStreamException {
System.out.println("调用了readResolve方法!");
return MyObjectHandler.myObject;
}
运行结果如下所示:
2133927002
调用了readResolve方法!
2133927002
是同一个对象
5.使用static代码块实现单例模式
静态代码块中的代码在使用类的时候就已经执行了,所以可以应用静态代码块的这个特性来实现单例设计模式。
创建项目,名称为6.5,创建类MyObject.java代码如下:
public class MyObject {
private static MyObject instance = null;
private MyObject() {
}
static {
instance = new MyObject();
}
public static MyObject getInstance() {
return instance;
}
}
创建线程类MyThread.java代码如下:
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(MyObject.getInstance().hashCode());
}
}
}
创建运行类Run.java代码如下:
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
运行结果如下所示:
1708263019
1708263019
1708263019
1708263019
1708263019
1708263019
1708263019
1708263019
1708263019
1708263019
1708263019
1708263019
1708263019
1708263019
1708263019
以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git