单例模式
在一个应用中保证某个类只存在单一实例(示例:springMVC中的bean可以设置为singleton)
下面介绍几种单例模式的实现:
1. 静态常量
public class SingletonClass1 {
private static SingletonClass1 singletonClass = new SingletonClass1();
private SingletonClass1(){}
public static SingletonClass1 getSingleton(){
return singletonClass;
}
public static void main(String[] args) {
SingletonClass1 singleton = SingletonClass1.getSingleton();
}
}
- 把对象作为静态变量,在声明时就进行实例化。
- 私有化构造方法
- 外界通过静态方法获取对象实例
优点
装载时完成实例化,线程安全。
缺点
没有懒加载,如果从来没有使用过这个实例,会造成内存浪费。
2. 静态代码块
public class SingletonClass2 {
private static SingletonClass2 singletonClass;
private SingletonClass2(){
singletonClass = new SingletonClass2();
}
public static SingletonClass2 getSingleton(){
return singletonClass;
}
public static void main(String[] args) {
SingletonClass2 singleton = SingletonClass2.getSingleton();
}
}
- 把对象作为静态变量。
- 私有化构造方法
- 将静态变量的实例化放在静态代码块中
- 外界通过静态方法获取对象实例
优点
装载时完成实例化,线程安全。
缺点
没有懒加载,如果从来没有使用过这个实例,会造成内存浪费。
3 静态方法
public class SingletonClass3 {
private static SingletonClass3 singletonClass;
private SingletonClass3(){
}
public static SingletonClass3 getSingleton(){
if(singletonClass == null ){
singletonClass = new SingletonClass3();
}
return singletonClass;
}
public static void main(String[] args) {
SingletonClass3 singleton = SingletonClass3.getSingleton();
}
}
- 把对象作为静态变量。
- 私有化构造方法
- 将静态变量的实例化放在静态方法中
- 外界通过静态方法获取对象实例
用户获取时会进行静态变量是否为空判断,空则实例化,非空返回引用
优点
起到懒加载效果、不会浪费内存。
缺点
线程不安全,线程发生上下文切换时,可能会造成获取到的类不同。
4. 静态同步方法
public class SingletonClass4 {
private static SingletonClass4 singletonClass;
private SingletonClass4(){
}
public static SingletonClass4 getSingleton(){
synchronized (SingletonClass1.class){
if(singletonClass == null ){
singletonClass = new SingletonClass4();
}
}
return singletonClass;
}
public static void main(String[] args) {
SingletonClass4 singleton = SingletonClass4.getSingleton();
}
}
与上一个相同,多一个synchronized关键字
优点
起到懒加载效果、不会浪费内存、线程安全。
缺点
多线程访问时效率低。
5. 同步代码块+双重检查
public class SingletonClass5 {
private static SingletonClass5 singletonClass;
private SingletonClass5(){
}
public static SingletonClass5 getSingleton(){
if(singletonClass == null ){
synchronized (SingletonClass1.class) {
if(singletonClass == null ) {
singletonClass = new SingletonClass5();
}
}
}
return singletonClass;
}
public static void main(String[] args) {
SingletonClass5 singleton = SingletonClass5.getSingleton();
}
}
优点:起到懒加载效果、不会浪费内存、线程安全。
6. 静态内部类
public class SingletonClass7 {
private SingletonClass7(){}
static class innerClass{
static SingletonClass7 singletonClass7 = new SingletonClass7();
}
public static SingletonClass7 getSingleton(){
return innerClass.singletonClass7;
}
public static void main(String[] args) {
SingletonClass7 singleton = SingletonClass7.getSingleton();
}
}
将单例对象以静态变量的形式放入静态内部类中,声明时即可实例化
外界通过外部类的静态方法获取内部静态类中的单例对象
(外部类的加载不会引起内部类的加载)
优点
起到懒加载效果、不会浪费内存、线程安全。
7. 枚举
public class SingletonClass6 {
private static SingletonClass6 singletonClass;
private SingletonClass6(){}
static enum SingletonEnum{
INSTANCE;
private SingletonClass6 singletonClass;
private SingletonEnum(){
singletonClass = new SingletonClass6();
}
public SingletonClass6 getInstance(){
return singletonClass;
}
}
public static SingletonClass6 getInstance(){
return SingletonEnum.INSTANCE.getInstance();
}
public static void main(String[] args) {
SingletonClass6 singleton = SingletonClass6.getInstance();
}
}
将单例对象放入枚举类最作为成员
优点:线程安全,还能防止反序列化时重新创建新的对象