单例即单个实例,在我们生产活动中有些类没必要好多实例存在的。

单例模式严格来讲有8种写法。

利用类加载器帮助我们实现单例模式。用jvm来保证我们的线程安全。

public class Mgr01{
private static final Mgr01 INSTANCE=new Mgr01();
private  Mgr01();
Public static Mgr01 getInstance{return  INSTANCE};
Public static void main(String[]args){
Mgr01 m1=Mgr01.getInstance();
Mgr01 m2=Mgr01.getInstance();
System.out.println(m1==m2);
}

唯一缺点,无论是否用到,都会有一个实例。

第一个稍微改造版,给第一个没什么区别。

public class Mgr02{
private static final Mgr02 INSTANCE;
Static{
INSTANCE=new Mgr01();
private  Mgr02();
Public static Mgr02 getInstance{return  INSTANCE};
Mgr02 m1=Mgr02.getInstance();
Mgr02 m2=Mgr02.getInstance();
懒汉式:达到初始化目的,带来了线程安全问题
public class Mgr03{
private static final Mgr03 INSTANCE;
private  Mgr03();
Public static Mgr03 getInstance(){
If(INSTANCE==null){
try{Thread.sleep(1);}catch(Exception e){}
Instance=new Mgr03();
Return Instance;
};
for(int i=0;i<1000;i++){
New Thread(()->{
System.out.println(Mgr03 .getInstance.hashCode());
}).start();
懒汉式进行改进
public class Mgr04{
private static final Mgr04 INSTANCE;
private  Mgr04();
Public static synchronized  Mgr04 getInstance(){
Instance=new Mgr04();
System.out.println(Mgr04 .getInstance.hashCode());

缺点:这样效率会降低,那有没有办法加锁的同时,效率也提高了。不在整个方法加锁。

public class Mgr05{
private static final Mgr05 INSTANCE;
private  Mgr05();
Public static Mgr05 getInstance(){
Synchronized(Mgr05 .class){
Instance=new Mgr05();}
System.out.println(Mgr05 .getInstance.hashCode());

在多线程访问下,不能做到只有一个实例。不能保证判断Instance为空的时候进来两个线程。

双重校验锁:

public class Mgr06{
private static final Mgr06 INSTANCE;
INSTANCE=new Mgr06();
private  Mgr06();
Public static Mgr06 getInstance(){
Synchronized(Mgr06 .class){
Instance=new Mgr06();}
System.out.println(Mgr06 .getInstance.hashCode());

静态内部类,jvm保证单实例,加载外部类不会加载内部类,这样可以实现懒加载.

public class Mgr07{
Private Static class Mgr07Holder{
private static final Mgr07 INSTANCE=new Mgr07 ();
private  Mgr07();
Public static Mgr07 getInstance(){
Return Mgr07Holder.Instance;
System.out.println(Mgr07 .getInstance.hashCode());

以上可以通过反射创建。

枚举模式创建单例,

public class EnumSingleton {
private EnumSingleton(){}
public static EnumSingleton getInstance(){
return Singleton.INSTANCE.getInstance();
}
private static enum Singleton{
INSTANCE;
private EnumSingleton singleton;
//JVM会保证此方法绝对只调用一次
private Singleton(){
singleton = new EnumSingleton();
}
public EnumSingleton getInstance(){
return singleton;

android 单例模式的应用场景 单例模式应用场景java_Public

单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:

1.需要频繁实例化然后销毁的对象。

2.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。

3.有状态的工具类对象。

4.频繁访问数据库或文件的对象。

以下都是单例模式的经典使用场景:

1.资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。

2.控制资源的情况下,方便资源之间的互相通信。如线程池等。

应用场景举例:

1.外部资源:每台计算机有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机。内部资源:大多数软件都有一个(或多个)属性文件存放系统配置,这样的系统应该有一个对象管理这些属性文件

2. Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗?不信你自己试试看哦~

3. windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。

4. 网站的计数器,一般也是采用单例模式实现,否则难以同步。

5. 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。

6. Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。

7. 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

8. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。

9. 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。

10. HttpApplication 也是单位例的典型应用。熟悉ASP.Net(IIS)的整个请求生命周期的人应该知道HttpApplication也是单例模式,所有的HttpModule都共享一个HttpApplication实例。

打开百度APP,查看更多高清图片

在spring中

spring的Bean默认的是单例的,Bean的作用域可以通过Bean标签的scope属性进行设置,Bean的作用域包括:

默认情况下scope="singleton",那么该Bean是单例,任何人获取该Bean实例的都为同一个实例;

scope="prototype",任何一个实例都是新的实例;

scope="request",在WEB应用程序中,每一个实例的作用域都为request范围;

scope="session",在WEB应用程序中,每一个实例的作用域都为session范围;

注意:在默认情况下,Bean实例在被Spring容器初始化的时候,就会被实例化,默认调用无参数的构造方法。在其它情况下,Bean将会在获取实例的时候才会被实例化。

在使用log4j框架时也注意到了其使用的是单例,当然也为了保证单个线程对日志文件的读写时不出问题,与使用spring管理bean的目标不是相似,如下为其logfactory单例创建的源码。