1:Java中单例模式是一种常见的设计模式,单例模式有以下特点:
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。 单例类必须给所有其他对象提供这一实例。
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
2:java中单例模式的写法也有很多种,我在这里列举几张常用的方式:
1、饿汉式,线程安全 但效率比较低:
/**
- 单例模式的实现:饿汉式,线程安全 但效率比较低
*/
public class SingletonTest {
// 定义一个私有的构造方法
private SingletonTest() {
}
// 将自身的实例对象设置为一个属性,并加上static和final修饰符
private static final SingletonTest instance = new SingletonTest();
// 静态方法返回该类的实例
public static SingletonTest getInstancei() {
return instance;
}
}
2、懒汉式,非线程安全:
/**
- 单例模式的实现:懒汉式,非线程安全
- */
public class SingletonTest {
// 定义私有构造方法(防止通过 new SingletonTest()去实例化)
private SingletonTest() {
}
// 定义一个SingletonTest类型的变量(不初始化,注意这里没有使用final关键字)
private static SingletonTest instance;
// 定义一个静态的方法(调用时再初始化SingletonTest,但是多线程访问时,可能造成重复初始化问题)
public static SingletonTest getInstance() {
if (instance == null)
instance = new SingletonTest();
return instance;
}
}
3、懒汉式,线程安全简单实现 :
/**
- 单例模式的实现:懒汉式,线程安全简单实现
- */
public class SingletonTest {
// 定义私有构造方法(防止通过 new SingletonTest()去实例化)
private SingletonTest() {
}
// 定义一个SingletonTest类型的变量(不初始化,注意这里没有使用final关键字)
private static SingletonTest instance;
// 定义一个静态的方法(调用时再初始化SingletonTest,使用synchronized 避免多线程访问时,可能造成重的复初始化问题)
public static synchronized SingletonTest getInstance() {
if (instance == null)
instance = new SingletonTest();
return instance;
}
}
4、线程安全 并且效率高 单例模式最优方案
/**
- 单例模式最优方案
- 线程安全 并且效率高
- */
public class SingletonTest {
// 定义一个私有构造方法
private SingletonTest() {
}
//定义一个静态私有变量(不初始化,不使用final关键字,使用volatile保证了多线程访问时instance变量的可见性,避免了instance初始化时其他变量属性还没赋值完时,被另外线程调用)
private static volatile SingletonTest instance;
//定义一个共有的静态方法,返回该类型实例
public static SingletonTest getIstance() {
// 对象实例化时与否判断(不使用同步代码块,instance不等于null时,直接返回对象,提高运行效率)
if (instance == null) {
//同步代码块(对象未初始化时,使用同步代码块,保证多线程访问时对象在第一次创建后,不再重复被创建)
synchronized (SingletonTest.class) {
//未初始化,则初始instance变量
if (instance == null) {
instance = new SingletonTest();
}
}
}
return instance;
}
}
5、静态内部类方式
/**
- 静态内部类方式
*
*/
public class Singleton {
private static class SingletonTest {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonTest.INSTANCE;
}
}
以上单例如设计模式即使有多重检查锁也可以通过反射破坏单例
6、目前最为安全的实现单例的方法是通过内部静态enum的方法来实现,因为JVM会保证enum不能被反射并且构造器方法只执行一次,事例如下:
/**
- 使用枚举的单例模式
* - @author uu
*/
public class EnumSingleton{
private EnumSingleton(){}
public static EnumSingleton getInstance(){
return Singleton.INSTANCE.getInstance();
}
private static enum Singleton{
INSTANCE;
private EnumSingleton singleton;
//JVM会保证此方法绝对只调用一次
private Singleton(){
singleton = new EnumSingleton();
}
public EnumSingleton getInstance(){
return singleton;
}
}
public static void main(String[] args) {
EnumSingleton obj0 = EnumSingleton.getInstance();
EnumSingleton obj1 = EnumSingleton.getInstance();
//输出结果:obj0==obj1?true
System.out.println("obj0==obj1?" + (obj0==obj1));
}
}
在此浅谈一下个人理解,希望对大家有所帮助。