单例模式
简介单例模式的写法饿汉模式懒汉模式静态内部类单例模式枚举单例模式
简介
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式的写法
饿汉模式
线程安全,通过JVM的类加载机制保证其只会有一个实例。写法示例
package designpattren
.hungrysingleton
;
public class HungrySingletonTest {
public static void main(String
[] args
) {
HungrySingleton instance
= HungrySingleton
.getInstance();
HungrySingleton instance1
= HungrySingleton
.getInstance();
System
.out
.println(instance
== instance1
);
}
}
class HungrySingleton{
private static HungrySingleton instance
=new HungrySingleton();
private HungrySingleton(){
}
public static HungrySingleton
getInstance(){
return instance
;
}
}
懒汉模式
线程不安全,用volatile关键字,防止JIT进行指令重排,导致的空指针问题,使得其可以在多线程环境下使用。写法示例
package designpattren
.lazysingleton
;
public class LazySingletonTest {
public static void main(String
[] args
) {
new Thread(()->{
LazySingleTon instance
=LazySingleTon
.getInstance();
System
.out
.println(instance
);
}).start();
new Thread(()->{
LazySingleTon instance
=LazySingleTon
.getInstance();
System
.out
.println(instance
);
}).start();
}
}
class LazySingleTon{
private volatile static LazySingleTon instance
;
private LazySingleTon(){
}
public static LazySingleTon
getInstance(){
if (instance
==null
){
synchronized (LazySingleTon
.class){
if(instance
==null
){
instance
= new LazySingleTon();
}
}
}
return instance
;
}
}
静态内部类单例模式
线程安全,通过静态内部类实现单例,同样依赖JVM的类加载机制保证它的线程安全。写法示例
package designpattren
.innerclasssingleton
;
import java
.io
.*
;
import java
.lang
.reflect
.Constructor
;
import java
.lang
.reflect
.InvocationTargetException
;
public class InnerClassSingletonTest {
public static void main(String
[] args
) throws NoSuchMethodException
, IllegalAccessException
, InvocationTargetException
, InstantiationException
, IOException
, ClassNotFoundException
{
InnerClassSingleton instance
= InnerClassSingleton
.getInstance();
ObjectOutputStream oos
= new ObjectOutputStream(new FileOutputStream("testSerializable"));
oos
.writeObject(instance
);
oos
.close();
ObjectInputStream ois
= new ObjectInputStream(new FileInputStream("testSerializable"));
Object object
=(InnerClassSingleton
)ois
.readObject();
System
.out
.println(instance
== object
);
}
}
class InnerClassSingleton implements Serializable {
static final long serialVersionUID
= 42L
;
private static class InnerClassHolder{
private static InnerClassSingleton instance
= new InnerClassSingleton();
}
private InnerClassSingleton(){
if(InnerClassHolder
.instance
!=null
){
throw new RuntimeException("单例不允许多个实例");
}
}
public static InnerClassSingleton
getInstance(){
return InnerClassHolder
.instance
;
}
Object
readResolve() throws ObjectStreamException
{
return InnerClassHolder
.instance
;
}
}
枚举单例模式
使用枚举实现的单例模式也是线程安全的,写法也比较简单,缺点是可读性比较低。这种方式下,也可以防止序列化攻击。写法示例
package designpattren
.enumsingleton
;
import java
.io
.FileInputStream
;
import java
.io
.FileOutputStream
;
import java
.io
.ObjectInputStream
;
import java
.io
.ObjectOutputStream
;
import java
.lang
.reflect
.Constructor
;
public enum EnumSingleton
{
INSTANCE
;
public void print(){
System
.out
.println(this.hashCode());
}
}
class EnumTest{
public static void main(String
[] args
) throws Exception
{
EnumSingleton instance
= EnumSingleton
.INSTANCE
;
ObjectInputStream ois
= new ObjectInputStream(new FileInputStream("test EnumSingleton"));
Object object
=( EnumSingleton
)ois
.readObject();
System
.out
.println(object
== instance
);
}
}