单例就是这么简单:
核心作用:
保证只有一个实例,并且提供一个访问该实例的全局访问点。
常见应用场景:
window的任务管理器和回收站
项目的配置文件
网站的计数器,一般是采用单例模式,否则难以同步
应用程序日志,共享日志文件一直处于单开状态,只有一个实例,才方便添加
数据库连接池
操作系统文件系统,一个操作系统只有一个文件系统
Application(servlet编程中)
spring中的Bean也是单例
Servlet、控制器都是单例
单例模式的有点:
由于只有一个实例,减少了系统性能开销,当一个对象的产生需要较多的资源时,如读取配置、产生其他对象依赖时
则可以通过在应用启动时候产生一个单例对象,然后永驻内存来解决
常见的五中种单例模式:
饿汉式(线程安全,调用效率高,但是不能延时加载)
懒汉式(线程安全,调用效率高,不能延时加载)
其他:
双重检测锁式(由于JVM低层内存模型原因,偶尔会出现问题,不建议使用)
静态内部类式(线程安全,调用效率高,可以延时加载)
枚举单例(线程安全,调用效率高,不能延时加载)
饿汉式:
public class Singleton{
private static final Singleton = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return s;
}
}
public class Singleton{
private static Singleton s;
private Singleton(){}
public static synchronized Singleton getInstance(){
if(s==null){
s = new Singleton();
}
return s;
}
}
public class Singleton{
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
Singleton sc;
synchronized(Singleton.class){
sc = instance;
if(sc==null){
synchronized(Singleton.class){
if(sc==null){
sc=new Singleton();
}
}
instance=sc;
}
}
}
return instance;
}
}
静态内部类:
public class Singleton{
private static class Singleton{
private static final Singleton instance = new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return Singleton.instance;
}
}
枚举实现:
public enum Yeshuai{
himself;
private String anotherField;
Yeshuai(){
himself = new Yeshuai();//其实这个方法可以去掉,在调用枚举的时候回自动创建对象
}
public void sayHello(){
System.out.println("hello yeshuai");
}
}
call:Yeshuai.himself.sayHello();
如何选用:
单例对象 占用资源少 不需要延时加载 枚举好于饿汉式
单例对象 占用资源大 需要延时加载 静态内部类好于懒汉式
多线程环境下测试时间效率对比
饿汉式: 22ms
懒汉式: 636ms
静态内部类:28ms
枚举式: 32ms
双重检查锁式: 65ms