单例模式

单例模式,最常见的就是饥饿模式和懒汉模式,一个直接实例化对象,一个在调用方法时进行实例化对象。
大家见的最多的莫过于下面这种单例模式了,这种模式是懒汉模式,就是说只有你调用getInstance方法的时候,它才会创建实例。但是这种方式有个非常致命的问题就是在多线程的情况下不能正常工作。

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
       if (instance == null) {  
          instance = new Singleton();  
       }  
       return instance;  
    }  
} 

懒汉模式要想线程安全,大家第一想到的便是下面这种方式,就是在getInstance方法加上synchronized关键字,但是这种方式也有致命的缺点,那就是并发率太低。

public class Singleton {  
 private static Singleton instance;  
 private Singleton (){}  
 public static synchronized Singleton getInstance() {  
    if (instance == null) {  
       instance = new Singleton();  
    }  
    return instance;  
 }  
}

上面是懒汉模式,下面我们再看下饿汉模式,如下所示。饿汉模式是典型的空间换取时间,当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候就不需要再判断了,节省了运行时间。但如果一直没有人调用,这种浪费的空间就不值得,特别是在空间不足的情况下。

public class Singleton {  
 private static Singleton instance = new Singleton();  
 private Singleton (){}  
 public static Singleton getInstance() {  
    return instance;  
 }  
} 
     在多线程模式中,考虑到性能和线程安全问题,我们一般选择下面两种比较经典的单例模式,在性能提高的同时,又保证了线程安全。

第一种方式:静态内部类
这种方式是最好的单例模式,而且还是线程安全的,为何这么说呢,静态内部类Singleton在初始化过程中是不会被加载的,只有当用户调用共用的getInstance方法时才会加载内部类Singleton并且实例化Singleton实例,也就是说,静态内部类这种方式也属于懒汉模式,只是实现方式不一样而已。之所以是线程安全的,是因为Singleton是静态的,静态内部类只会被实例化一次,也就是说不管有多少线程,大家拿到的是同一个实例,不会再去进行多次实例化,从而达到了线程安全的目的。由于没有加锁,所以并发性特别高,线程还安全,所以大家以后碰到单例模式,用静态内部类最为合适。如下图所示。
代码如下:

package com.internet.singleton;

public class InnerSingleton {
 private static class Singleton{
 	private static InnerSingleton single = new InnerSingleton();
 }
 
 public static InnerSingleton getInstance(){
 	return Singleton.single;
 }
}

第二种方式:双重检查

package com.internet.singleton;

public class DubbleSingleton {
 
 private static DubbleSingleton ds;
 
 public static DubbleSingleton getDs(){
 	if(ds == null){
 		try {
 			//模拟初始化对象的准备时间...
 			Thread.sleep(3000);
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
 		synchronized (DubbleSingleton.class) {
 			if(ds == null){
 				ds = new DubbleSingleton();
 			}
 		}
 	}
 	return ds;
 }
 
 public static void main(String[] args){
 	Thread t1 = new Thread(new Runnable() {
 		
 		@Override
 		public void run() {
 			System.out.println(DubbleSingleton.getDs().hashCode());
 		}
 	},"t1");
 	
 	Thread t2 = new Thread(new Runnable() {
 		
 		@Override
 		public void run() {
 			System.out.println(DubbleSingleton.getDs().hashCode());
 		}
 	},"t2");
 	
             Thread t3 = new Thread(new Runnable() {
 		
 		@Override
 		public void run() {
 			System.out.println(DubbleSingleton.getDs().hashCode());
 		}		},"t3");
     
             t1.start();
             t2.start();
             t3.start();
 }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值