java 单例模式

java 单例模式是什么?

单例模式:确保一个类只有一个实例,并提供一个全局访问点。如果使用多个类加载器,可能导致单例失效而产生多个实例。

实例如下:

// 经典单例模式:此例不是线程安全的例子
// 优点:在获取实例的方法中,进行实例的初始化,节省系统资源
// 缺点:1.如果获取实例时,初始化工作较多,加载速度会变慢,影响系统系能
// 2.每次获取实例都要进行非空检查,系统开销大
// 3.非线程安全,当多个线程同时访问getInstance()时,可能会产生多个实例
class Singleton {
	private static Singleton uniqueInstance; // 1.静态的单例变量 
	private Singleton() {} // 2.私有的构造器
	public static Singleton getInstance() { // 3.静态方法
		if ( uniqueInstance == null ) { // 延迟实例化
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	} 
	// 这里还有其他有用的方法
	public String getDescription() { // 获取描述
		return "I'm a classic Singleton!";
	}
}
class SingletonClient { // 单例客户端
	public static void main( String[] args ) {
		Singleton singleton = Singleton.getInstance();
		System.out.println( singleton.getDescription() );
	}
}
public class Test0524{
	public static void main( String[] args ){
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		System.out.println( "s1 == s2 : " + ( s1 == s2 ) );
	}
}
----------------------------------------------------------------
E:\java>java Test0524
s1 == s2 : true
// 线程不安全的单例怎么样解决?
class ChocolateBoiler { // 巧克力锅炉
	private boolean empty; // 空的
	private boolean boiled; // 煮好的
	private static ChocolateBoiler uniqueInstance;  // 单一实例
	
	private ChocolateBoiler() {
		empty = true;
		boiled = false;
	}  
	public static ChocolateBoiler getInstance() { // 获取实例
		if ( uniqueInstance == null ) {
			System.out.println( "Creating unique instance of Chocolate Boiler" );
			uniqueInstance = new ChocolateBoiler();
		}
		System.out.println( "Returning instance of Chocolate Boiler" );
		return uniqueInstance;
	}
	public void fill() { // 注满
		if ( isEmpty() ) {
			empty = false;
			boiled = false;
			// fill the boiler with a milk/chocolate mixture
		}
	} 
	public void drain() { // 沥干
		if ( !isEmpty() && isBoiled() ) { 
			// drain the boiled milk and chocolate
			empty = true;
		}
	} 
	public void boil() { // 煮
		if ( !isEmpty() && !isBoiled() ) {
			// bring the contents to a boil
			boiled = true;
		}
	}  
	public boolean isEmpty() { // 空的
		return empty;
	} 
	public boolean isBoiled() { // 煮好的
		return boiled;
	}
}
class ChocolateController { // 巧克力控制器
	public static void main( String args[] ) {
		ChocolateBoiler boiler = ChocolateBoiler.getInstance();
		boiler.fill();
		boiler.boil();
		boiler.drain();

		// will return the existing instance
		ChocolateBoiler boiler2 = ChocolateBoiler.getInstance();
	}
}
// 1.同步getInstance()方法/ 线程安全但性能差。
// 优点:线程安全
// 缺点:每次获取实例都要加锁,耗费资源,其实只要实例已经生成,以后获取就不需要再锁了
class Singleton {
	private static Singleton uniqueInstance; 
	// 这里可以加入其他有用的实例变量 
	private Singleton() {} 
	// 同步一个方法可能造成程序执行效率下降100倍。
	public static synchronized Singleton getInstance() { // 同步的
		if ( uniqueInstance == null ) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	} 
	// other useful methods here
	public String getDescription() {
		return "I'm a thread safe Singleton!";
	}
}
class SingletonClient { 
	public static void main( String[] args ) {
		Singleton singleton = Singleton.getInstance();
		System.out.println( singleton.getDescription() );
	}
}
// 2.急切实例化/ 饿汉式:不用延迟实例化
// 好处:线程安全;获取实例速度快 
// 缺点:类加载即初始化实例,内存浪费
class Singleton {
	private static Singleton uniqueInstance = new Singleton();
 
	private Singleton() {} 
	public static Singleton getInstance() {
		return uniqueInstance;
	}	
	// other useful methods here
	public String getDescription() {
		return "I'm a statically initialized Singleton!";
	}
}
class SingletonClient {
	public static void main( String[] args ) {
		Singleton singleton = Singleton.getInstance();
		System.out.println( singleton.getDescription() );
	}
}
// 3.双重检查加锁/ 此例在Java 5之前不能保证单例的实现。
// 优点:线程安全,进行双重检查,保证只在实例未初始化前进行同步,效率高
// 缺点:还是实例非空判断,耗费一定资源
class Singleton { // 单例模式
	private volatile static Singleton uniqueInstance; // volatile:轻量级同步机制
 
	private Singleton() {} 
	public static Singleton getInstance() { // 获取实例
		if ( uniqueInstance == null ) {
			synchronized ( Singleton.class ) { // 重量级同步锁
				if ( uniqueInstance == null ) {
					uniqueInstance = new Singleton();
				}
			}
		}
		return uniqueInstance;
	}
}
class SingletonClient { // 单例客户端
	public static void main( String[] args ) {
		Singleton singleton = Singleton.getInstance();
	}
}
// 4.静态内部类
// 优点:既避免了同步带来的性能损耗,又能够延迟加载
class Singleton {
    private Singleton(){} 
    private static class Holder {
        private static Singleton singleton = new Singleton();
    } 
    public static Singleton getSingleton(){
        return Holder.singleton;
    }
}
// 上面提到的所有实现方式都有两个共同的缺点:
// 1.需要额外的工作(Serializable、transient、readResolve())来实现序列化,否则每次反序列化一个序列化的对
// 象实例时都会创建一个新的实例。
// 2.可能会有人使用反射强行调用我们的私有构造器(如果要避免这种情况,可以修改构造器,让它在创建第二个实
// 例的时候抛异常)。
// 5.枚举类型:天然线程安全,可防止反射生成实例。
// 使用枚举除了线程安全和防止反射强行调用构造器之外,还提供了自动序列化机制,防止反序列化的时候创建新的
// 对象。因此,Effective Java推荐尽可能地使用枚举来实现单例。
enum Singleton { // 枚举类型
    INSTANCE; // 单例常量
    private String name;
    public String getName(){
        return name;
    }
    public void setName( String name ){
        this.name = name;
    }
}
public class Test0524{ // 枚举类型的用法
	public static void main( String[] args ){
		Singleton singleton = Singleton.INSTANCE;
		singleton.setName( "This is a SingletonInstance" );
		System.out.println( singleton.getName() );
	}
}
// 继承会导致所有的派生类共享同一个实例变量
class Singleton {
	protected static Singleton uniqueInstance;
 
	// other useful instance variables here 
	protected Singleton() {} // 别的类也可以实例化它
	public static synchronized Singleton getInstance() {
		if ( uniqueInstance == null ) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	} 
	// other useful methods here
}
class CoolerSingleton extends Singleton { // 冷却器单例
	// useful instance variables here
	protected static Singleton uniqueInstance;
 
	private CoolerSingleton() {
		super();
	} 
	// useful methods here
}
class HotterSingleton extends Singleton { // 加热器单例
	// useful instance variables here 
	private HotterSingleton() {
		super();
	} 
	// useful methods here
}
class SingletonTestDrive {
	public static void main( String[] args ) {
		Singleton foo = CoolerSingleton.getInstance();
		Singleton bar = HotterSingleton.getInstance();
		System.out.println( foo );
		System.out.println( bar );
 	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值