一.单例模式有八种方式:
-
饿汉式(静态常量)
特点:类加载就创建对象
代码:
public class SingletonTest01 {
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.print(instance1==instance2);
}
}
class Singleton{
//构造器私有化
private Singleton(){}
//内部创建对象实例
private final static Singleton instance=new Singleton();
//对外提供对象实例
public static Singleton getInstance() {
return instance;
}
}
优点:1.类装载时完成类实例化,避免了线程安全问题。
缺点:1.类装载时完成类实例化,没有懒加载,如果没有用过造成内存资源浪费。
- 饿汉式(静态代码块)
代码:
public class SingletonTest02 {
public static void main(String[] args) {
Singleton2 instance1 = Singleton2.getInstance();
Singleton2 instance2 = Singleton2.getInstance();
System.out.print(instance1==instance2);
}
}
class Singleton2{
//构造器私有化
private Singleton2(){}
private static Singleton2 instance;
static {
//静态代码块加载时创建对象实例
instance=new Singleton2();
}
//对外提供对象实例
public static Singleton2 getInstance() {
return instance;
}
}
优缺点跟静态常量一样。
-
懒汉式(线程不安全)
特点:当使用发现不存在才会创建对象,存在并发问题。
代码:
public class SingletonTest03 {
public static void main(String[] args) {
Singleton3 instance1 = Singleton3.getInstance();
Singleton3 instance2 = Singleton3.getInstance();
System.out.println(instance1==instance2);
}
}
class Singleton3{
//构造器私有化
private Singleton3(){}
private static Singleton3 instance;
//对外提供对象实例
public static Singleton3 getInstance() {
if(instance==null){
instance=new Singleton3();
}
return instance;
}
}
缺点:线程不安全,有概率存在相同对象。
-
懒汉式(线程安全,同步方法)
特点:为了解决线程安全问题,加入同步代码器,但是效率低。
代码:
public class SingletonTest04 {
public static void main(String[] args) {
Singleton4 instance1 = Singleton4.getInstance();
Singleton4 instance2 = Singleton4.getInstance();
System.out.println(instance1==instance2);
}
}
class Singleton4{
//构造器私有化
private Singleton4(){}
private static Singleton4 instance;
//对外提供对象实例 加入同步关键字保证线程安全
public static synchronized Singleton4 getInstance() {
if(instance==null){
instance=new Singleton4();
}
return instance;
}
}
缺点:方法进行同步,效率太低。
-
懒汉式(线程安全,同步代码块)
特点:为了降低锁力度,对创建对象进行线程同步。
代码:
public class SingletonTest05{
public static void main(String[] args) {
Singleton5 instance1 = Singleton5.getInstance();
Singleton5 instance2 = Singleton5.getInstance();
System.out.println(instance1==instance2);
}
}
class Singleton5{
//构造器私有化
private Singleton5(){}
private static Singleton5 instance;
//对外提供对象实例 加入同步代码块解决
public static synchronized Singleton5 getInstance() {
if(instance==null){
synchronized (Singleton5.class){
instance=new Singleton5();
}
}
return instance;
}
}
缺点:仅仅对创建对象进行同步处理,对判断有无存在对象没做线程同步,并发问题依然存在。
-
双重检查
特点:锁力度进一步缩小,对核心模块加锁,外围模块不加锁保证效率,加入
volatile保证可见性和避免指令重拍
代码:
public class SingletonTest06{
public static void main(String[] args) {
Singleton6 instance1 = Singleton6.getInstance();
Singleton6 instance2 = Singleton6.getInstance();
System.out.println(instance1==instance2);
}
}
class Singleton6{
//构造器私有化
private Singleton6(){}
//对多个线程可见 防止指令重排
private static volatile Singleton6 instance;
//对外提供对象实例 加入同步代码块解决
public static synchronized Singleton6 getInstance() {
//双重检查
if(instance==null){
synchronized (Singleton6.class){
if(instance==null){
instance=new Singleton6();
}
}
}
return instance;
}
}
优点:线程安全;延迟加载;效率较高。
-
静态内部类
特点:利用静态内部类和外部类装载时间不同实现懒加载;jvm装载类时线程安全
代码:
public class SingletonTest07{
public static void main(String[] args) {
Singleton7 instance1 = Singleton7.getInstance();
Singleton7 instance2 = Singleton7.getInstance();
System.out.println(instance1==instance2);
}
}
class Singleton7 {
//构造器私有化
private Singleton7(){}
//对多个线程可见 防止指令重排
private static volatile Singleton7 instance;
//静态内部类,该类有一个静态属性Singleton
private static class SingletonInstance{
private static final Singleton7 INSTANCE=new Singleton7();
}
//装载Singleton7不会马上装载静态内部类SingletonInstance,同时调用getInstance()会装载SingletonInstance,jvm在装载类时线程安全
public static Singleton7 getInstance() {
return SingletonInstance.INSTANCE;
}
}
优点:线程安全;延迟加载;jvm类装载机制
-
枚举
特点:防止反序列化重新创建对象
代码:
public class SingletonTest08 {
public static void main(String[] args) {
Singleton8 instance1 = Singleton8.INSTANCE;
Singleton8 instance2 = Singleton8.INSTANCE;
System.out.println(instance1==instance2);
}
}
//使用枚举实现单例 防止反序列化重新创建对象
enum Singleton8{
INSTANCE;//属性
public void say(){
System.out.println("ok");
}
}
优点:防止反序列化重新创建对象
JDK实例: