**单例模式 顾名思义就是在程序中只有一个实例对象
单例模式具体大致分为两种类型:
1.懒汉式
-
懒汉式顾名思义就是能有多懒他就多懒,能不’动’他就不动
-
懒汉式只有在需要他的时候他才会去加载,完成实例化
2.饿汉式
-
饿汉式顾明思义就是不管三七二十一就是要’吃’,不管是否需要,先’吃’了再说
-
饿汉式在程序类加载的时候完成实例化
以下是各实例的Demo
1.饿汉式
/**
* 饿汉式(最常见)
* 类加载到内存后,就实例化一个单例,JVM保证线程的安全
* 1.将对象声明
* 2.对象的构造方法设为私有属性,用户在使用的时候无法去声明创建对象
* 3.写一个getInstance方法,去返回类中声明的唯一对象
* 缺点:类加载的时候完成实例化
*/
public class Singleton {
private static final Singleton singleton=new Singleton();
private Singleton(){};
public static Singleton getInstance(){
return singleton;
}
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance.hashCode());
System.out.println(instance2.hashCode());
}
//两者输出的hash值一致
2.懒汉式
/**
* 懒汉式
* 1.声明实例,但是不初始化
* 2.在构造方法私有化
* 3.在调取getInstance进行对象返回的时候,判断对象是否为null,是否初始化完成
* 3.1 初始化完成,既不为null,那就返回对象,否则进行对象的初始化
* 缺点: 在多线程的访问中是有问题的 ---不安全
*/
public class Singleton01 {
private static Singleton01 singleton=null;
private Singleton01(){};
public static Singleton01 getInstance(){
if(singleton==null){
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
singleton=new Singleton01();
}
return singleton;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()-> {
System.out.println(Singleton01.getInstance().hashCode());
}).start();
}
}
}
3.懒汉式(改进上个版本多线程下出现的问题)
在方法上加锁 加锁的同时,会影响程序的效率
/**
* 懒汉式
* 1.声明实例,但是不初始化
* 2.在构造方法私有化
* 3.在调取getInstance进行对象返回的时候,判断对象是否为null,是否初始化完成
* 3.1 初始化完成,既不为null,那就返回对象,否则进行对象的初始化
* 缺点: 在多线程的访问中是有问题的 ---不安全
*
* 修改 01: 在方法上加锁 加锁的同时,会影响程序的效率
*/
public class Singleton02 {
private static Singleton02 singleton=null;
private Singleton02(){};
public static synchronized Singleton02 getInstance(){
if(singleton==null){
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
singleton=new Singleton02();
}
return singleton;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()-> {
System.out.println(Singleton02.getInstance().hashCode());
}).start();
}
}
}
4.懒汉式(上个版本在方法上加锁,导致程序的运行效率大大降低)
改进: 在方法内部加锁
/**
* 懒汉式 (较为完美)
* 1.声明实例,但是不初始化
* 2.在构造方法私有化
* 3.在调取getInstance进行对象返回的时候,判断对象是否为null,是否初始化完成
* 3.1 初始化完成,既不为null,那就返回对象,否则进行对象的初始化
* 缺点: 在多线程的访问中是有问题的 ---不安全
*
* 修改 01: 在方法内部加锁 加锁的同时,会影响程序的效率
* 需要进行两次判空,一次判断在多线程的时候,容易造成多次声明对象
*/
public class Singleton03 {
private static Singleton03 singleton=null;
private Singleton03(){};
public static Singleton03 getInstance(){
if(singleton==null){
synchronized (Singleton03.class) {
if(singleton==null) {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
singleton = new Singleton03();
}
}
}
return singleton;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()-> {
System.out.println(Singleton03.getInstance().hashCode());
}).start();
}
}
}
在方法内部加锁比在方法上加锁,效率影响小
5.懒汉式(懒汉式目前完美的方法)
/**
* 懒汉式(完美)
* 1.声明一个静态内部类的对象声明
* JVM保证线程安全
*/
public class Singleton04 {
private Singleton04(){};
private static class MySingleton04{
private static final Singleton04 singleton=new Singleton04();
}
public static Singleton04 getInstance(){
return MySingleton04.singleton;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()-> {
System.out.println(Singleton04.getInstance().hashCode());
}).start();
}
}
}
6.使用枚举类完成懒汉式
/**
* 懒汉式(完美)
* 优点:使用JDK1.5提供的枚举来实现单例设计模式,不仅能避免多线程同步问题,
* 而且还能防止反序列化创建新的对象,这种方式是Effective java中提倡的方式
*
*/
public enum Singleton05 {
INSTANCE;
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()-> {
System.out.println(Singleton05.INSTANCE);
}).start();
}
}
}
以上便是对单例模式较为详细的Demo,目前还是对枚举类的这种方法有点懵,如果有大佬看到,还请指点一二!!!