一、单例模式
单例模式分为 八种、
饿汉:先给我 ,就是什么都创建好 等着被调用 可能造成内存浪费
懒汉:饿了在给我 就是:什么时候用 什么时候创建
单例模式注意事项和细节说明
- 单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使 用单例模式可以提高系统性能
- 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用 new
单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级 对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session 工厂等)
1.1、饿汉式静态变量
实现步骤:
- 构造器私有化 (防止 new )
- 本类的内部创建对象实例
- 提供一个公有的静态方法,返回实例对象
-
优点:写法简单、在启动项目,类装载时 就完成了其实例化对象,避免线程同步的问题
-
缺点:如果这个类对象用不到,但还是实例化了,造成了内存浪费
-
结论:这种单例模式 可用,但 可能造成内存浪费,如果 这种单例太多,启动时一次性加载,啧啧啧,可怕的
public class A_SingletonPattern {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
// 证明对象是同个对象
System.out.println(instance == instance1); // true
System.out.println("instance hashCode = " + instance.hashCode()); // instance hashCode = 789451787
System.out.println("instance1 hashCode = " + instance.hashCode()); // instance1 hashCode = 789451787
}
}
// 饿汉式(静态常量)
class Singleton{
// 1、私有化 构造器
private Singleton(){
}
// 2、类的内部创建对象实例
private final static Singleton instance = new Singleton();
// 3、提供一个公有的静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
}
解读代码:
对 Singleton类
1、私有化构造器,防止new它
// 1、私有化 构造器
private Singleton(){
}
2、类的内部创建对象实例 静态的且是常量 在启动项目是 就创建了该对象
private final static Singleton instance = new Singleton();
3、提供一个公有的静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
main 方法 通过== 和 对象的hashcode 验证是同一个 Singleton 对象
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
// 证明对象是同个对象
System.out.println(instance == instance1); // true
System.out.println("instance hashCode = " + instance.hashCode()); // instance hashCode = 789451787
System.out.println("instance1 hashCode = " + instance.hashCode()); // instance1 hashCode = 789451787
}
1.2、饿汉式 静态代码块
class SingletonB {
// 1、私有化 构造器
private SingletonB() {
}
// 2、类的内部创建对象实例
private static SingletonB instance;
// 在静态代码块中,创建单例对象
static {
instance = new SingletonB();
}
// 3、提供一个公有的静态方法,返回实例对象
public static SingletonB getInstance() {
return instance;
}
}
代码解读:
静态常量类似,只不过将类实例化的过程放在了静态代码块中,也是在类装载的时候,就执 行静态代码块中的代码,初始化类的实例。
// 2、类的内部创建对象实例
private static SingletonB instance;
// 在静态代码块中,创建单例对象
static {
instance = new SingletonB();
}
1.3、懒汉式(单线程)
线程不安全 只能在单线程下使用
优缺点:
- 起到了 懒加载(Lazy Loading) 的效果,调用的时候再创建对象实例 但只能单线程下使用
- 如果在多线程下 ,一个线程第一个走到 if (instance == null) 这是需要创建一个对象,
但是还没来得及往下走,另一个线程也走到这 也要去创建一个对象,这就会产生多个实例
结论:不要使用该方式 除非 上锁 synchronized 效率慢
class SingletonC{
// 1、私有化 构造器
private SingletonC(){
}
private static SingletonC instance;
// 3、提供一个公有的静态方法,调用的时候 再创建该对象的实例
public static SingletonC getInstance(){
if (instance == null){
instance = new SingletonC();
}
return instance;
}
}
1.4、 懒汉式(线程安全)
优缺点:
- 解决线程安全问题
- 效率太低了 ,该方法每次只能有一个线程进入,效率降低
结论:不推荐使用这种方式
class SingletonD{
// 1、私有化 构造器
private SingletonD(){
}
private static SingletonD instance;
// 3、提供一个公有的静态方法,加入synchronized 解决线程安全问题 效率 低
public static synchronized SingletonD getInstance(){
if (instance == null){
instance = new SingletonD();
}
return instance;
}
}
使用 synchronized 保证线程安全
1.5、双重检查
上代码: