1. 核心作用
:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
常见应用场景:
– Windows的Task Manager(任务管理器)就是很典型的单例模式– windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。
– 项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,每次new一个对象去读取。
– 网站的计数器,一般也是采用单例模式实现,否则难以同步。
– 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作
,否则内容不好追加。
– 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。
– 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。
– Application 也是单例的典型应用(Servlet编程中会涉及到)
– 在Spring中,每个Bean默认就是单例的,这样做的优点是Spring容器可以管理
– 在servlet编程中,每个Servlet也是单例
– 在spring MVC框架/struts1框架中,控制器对象也是单例
单例模式的优点:
– 由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时,直接产生一个单例对象,然后永久驻留内存的方式来解决
– 单例模式可以在系统设置全局的访问点,优化环共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理
• 常见的五种单例模式实现方式:
– 主要:
• 饿汉式(线程安全,调用效率高。 但是,不能延时加载。)
• 懒汉式(线程安全,调用效率不高。 但是,可以延时加载。)
– 其他:
• 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用)
• 静态内部类式(线程安全,调用效率高。 但是,可以延时加载)
• 枚举单例(线程安全,调用效率高,不能延时加载)
代码如下:
package org.singleton;
/**
* 单例模式: 核心作用 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
* 优点:单例模式只生成一个实例 减少了系统的性能开销
*
*/
/**
*
* 饿汉式 (线程安全 调用效率高 但是不能延迟加载)
* 线程安全指的就是 多个线程对象 去访问
*/
public class Singleton01 {
private static final Singleton01 s=new Singleton01();
private Singleton01(){}
//synchronized 可以省略
//static 变量会在类装载时初始化,此时也不会涉及多个线程对象同时访问该对象s的问题
// 而 虚拟机保证 类只加载一次
public static synchronized Singleton01 getInstance(){
return s;
}
}
package org.singleton;
/**
* 懒汉式 实现(单例对象延迟加载)
*
*/
public class Singleton02 {
private static Singleton02 s;
private Singleton02(){}
//缺点:每次调用getInstance都要同步 ,效率低下
public static synchronized Singleton02 getInstance(){
if(s==null){
s=new Singleton02();
}
return s;
}
}
双重检测锁可以看这里 https://blog.csdn.net/gangjindianzi/article/details/78689713
package org.singleton;
/**
* 双重检测锁实现 不推荐使用
*
*/
public class Singleton03 {
private static Singleton03 instance=null;
private Singleton03() {
}
public static Singleton03 getInstance(){
if(instance==null){
Singleton03 sc;
synchronized(Singleton03.class){
sc=instance;
if(sc==null){
synchronized (Singleton03.class) {
if(sc==null){
sc=new Singleton03();
}
}
instance=sc;
}
}
}
return instance;
}
}
package org.singleton;
/**
* 测试静态内部类 实现单例模式
* 这种方式:线程安全 调用效率高,实现了延时加载
*
*/
public class Singleton04 {
private static class SingletonClassInstance{
private static final Singleton04 instance=new Singleton04();
}
private Singleton04(){}
public static Singleton04 getInstance(){
return SingletonClassInstance.instance;
}
}