详解单例模式

看代码

/**
 * 单利模式分设计3要素:
 * 1、构造函数私有化,使其不能在外部使用new关键字实例化对象
 * 2、在该类内部产生一个唯一实例化对象,并且将其封装成private static类型
 * 3、定义一个静态方法返回该唯一对象
 * 单例模式包含两种:饿汉式和懒汉式
 * 饿汉式:使用类的时候已经将对象创建完毕,通常的做法就是在定义的时候实例化对象
 * 优点:实现简单,不存在线程同步问题;
 * 缺点:占用内存
 * @author Lenovo
 *
 */
public class Singleton {

	//将对象设置为一个属性,并且用private static修饰,产生一个唯一属性
	private static final Singleton instance = new Singleton(); //饿汉式
	
	// 构造方法私有化
	private Singleton(){
		System.out.println("****Singletong Constructor*******");
	}
	//静态方法返回创建的对象
	public static Singleton getInstance(){
		return instance;
	}

	public void print(){
		System.out.println("*****单利类******");
	}
}

测试结果:

一、单线程:

public static void main(String[] args) {
    Singleton singleton = Singleton.getInstance();
    singleton.print();
}

print:
*****单利类******

二、多线程:

public class DemoMain {

	public static void main(String[] args) {
		
		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				public void run() {
					Singleton.getInstance().print();
				}
			}, "线程" + i).start();
		}
	}
}

print:
****Singletong Constructor*******
*****单利类******
*****单利类******
*****单利类******

以上测试可见:Singleton的构造函数只执行了一次,说明不存在线程不同步的问题。

第二类:懒汉式:

/**
 * 懒汉式:在使用的时候再创建实例化对象,懒,顾名思义就是不提前做准备,用的时候再创建。
 * 优点:特定情况下节约内存;
 * 缺点:存在线程不同步问题,不能实现对象的唯一性。
 * @author Lenovo
 *
 */
public class Singleton {

	//将对象设置为一个属性,并且用private static修饰,产生一个唯一属性
	private static Singleton instance = null; //懒汉式
	
	// 构造方法私有化
	private Singleton(){
		System.out.println("****Singletong Constructor*******");
	}
	//静态方法返回创建的对象
	public static Singleton getInstance(){
		
		if (null == instance){
			instance = new Singleton();
		}
		
		return instance;
	}

	public void print(){
		System.out.println("*****"+ Thread.currentThread().getName() +"单利类******");
	}
}

多线程测试(测试代码不变):

****Singletong Constructor*******
****Singletong Constructor*******
*****线程2单利类******
****Singletong Constructor*******
*****线程0单利类******
*****线程1单利类******

从上面的结果看出,Singleton的构造函数执行力3次,说明实例化了3个对象,出现了不同步问题。

为了解决不同步问题,可以在getInstance函数增加synchronized关键字,即:

//静态方法返回创建的对象
public static synchronized Singleton getInstance(){
    if (null == instance){
	instance = new Singleton();
    }
		
    return instance;
}

synchronized关键字虽然解决了线程,却引入了效率问题,通常的解决方式式在实例化的程序块增加synchronized关键字,即:

/**
 * 懒汉式:在使用的时候再创建实例化对象,懒,顾名思义就是不提前做准备,用的时候再创建。
 * 优点:特定情况下节约内存;
 * 缺点:存在线程不同步问题,不能实现对象的唯一性。
 * @author Lenovo
 *
 */
public class Singleton {

	//将对象设置为一个属性,并且用private static修饰,产生一个唯一属性
	private static Singleton instance = null; //懒汉式
	
	// 构造方法私有化
	private Singleton(){
		System.out.println("****Singletong Constructor*******");
	}
	//静态方法返回创建的对象
	public static Singleton getInstance(){
		
		if (null == instance){
			synchronized (Singleton.class) {
				if (null == instance){
					instance = new Singleton();
				}
			}
		}
		
		return instance;
	}

	public void print(){
		System.out.println("*****"+ Thread.currentThread().getName() +"单利类******");
	}
}

猜你喜欢

转载自blog.csdn.net/haoyue1014/article/details/86671824