单例就是应用的整个生命周期只能存在一个实例.属于创建类型的一种常用的软件设计模式
单例有三个要求:
1:只能有一个实例
2:他必须自行创建这个实例
3:他必须自行向整个系统提供实例.
应用的实例:
一个应用中只有一个实例,就好像一个班级只有一个班主任来进行管理一样.
可以实现单例的方法有五种,我们常见的有两种饿汉式和懒汉式
- 饿汉式:初始化实例的时候就已经new出来了,好处是没有线程安全的问题,坏处是因为上来不管用不用只能新建所以浪费内存
- 懒汉式:当我需要用到实例的时候才会检索有没有实例,有就直接返回,没有就新建一个
- 双检索式:综合了饿汉式和懒汉式的优缺点,加了一层判断语句,既保证了线程安全,也节省了空间.
- 静态内部类:只适用于静态域的情况
- 枚举:自动支持序列化机制,绝对防止多次实例化
package Test.singleton;
/**
* @author LZP
* @create 2020/5/10
*/
public class Hungry {
/**
* 懒汉式
*/
//创建对象
private static Hungry instance = new Hungry();
//构造函数私有化,就类就不会实例化了
public Hungry(){}
//获取唯一可用对象
public static Hungry getInstance(){
return instance;
}
public void show(){
System.out.println("这是饿汉式,好处是执行效率变高。缺点是浪费内存");
}
}
package Test.singleton;
/**
* @author LZP
* @create 2020/5/10
*/
public class Idler {
private static Idler idler;
public Idler(){}
public static synchronized Idler getInstance(){
if (idler == null) {
idler = new Idler();
}
return idler;
}
public void show(){
System.out.println("这是懒汉式,加了if判断线程安全");
}
}
package Test.singleton;
/**
* @author LZP
* @create 2020/5/10
*/
public class DCL {
/**
* 双检索
*/
//volatile不稳定
private volatile static DCL dcl;
private DCL(){}
public static DCL getDcl(){
if (dcl == null) {
//synchronized同步
synchronized (DCL.class){
if (dcl == null) {
dcl = new DCL();
}
}
}
return dcl;
}
public void show(){
System.out.println("这是双检索。综合了饿汉式和懒汉式的优缺点。");
}
}
package Test.singleton;
/**
* @author LZP
* @create 2020/5/10
*/
public class Static1 {
private static class Test{
//final不可更改
private static final Static1 a = new Static1();
}
private Static1(){}
public static final Static1 getInstance(){
return Test.a;
}
private static void show(){
System.out.println("这是静态内部类");
}
}
package Test.singleton;
/**
* @author LZP
* @create 2020/5/11
*/
public enum Enumeration {
/***
* 枚举
*/
TEST,TEST1;
public void show(){
System.out.println("这是枚举");
}
}
package Test.singleton;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author LZP
* @create 2020/5/10
*/
public class Test {
/**
* 测试类
*/
//懒汉式
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException, IllegalAccessException {
Hungry instance = Hungry.getInstance();
instance.show();
System.out.println("******");
Idler instance1 = Idler.getInstance();
instance1.show();
System.out.println("******");
DCL dcl = DCL.getDcl();
dcl.show();
System.out.println("******");
Static1 instance2 = Static1.getInstance();
//此处用到反射
Class<?> aClass = Class.forName("Test.singleton.Static1");
Method show = aClass.getDeclaredMethod("show");
show.setAccessible(true);
show.invoke("show");
System.out.println("******");
Enumeration.TEST.show();
Enumeration.TEST1.show();
}
}