单例设计模式简介及测试

测试思路:
用十个线程测试一下,核心思想是用线程获取对象的哈希值,如果一致证明线程安全,反之线程不安全。代码如下:

package single;
public class TestSingle {
	public static void main(String[] args) {
		   ThreadTest[] ThreadArr = new ThreadTest[10];//创建线程数组
	        for (int i = 0; i < ThreadArr.length; i++) {
	            ThreadArr[i] = new ThreadTest();//轮流创建线程
	            ThreadArr[i].start();//轮流执行
	        }
	    }
	}
	class ThreadTest extends Thread{
		public void run() {
			System.out.println(HungryPerson.getHungryPerson().hashCode());//以饿汉为例,轮流打印对象的哈希值
		}
	}

饿汉模式:
饿汉模式按发传单来比喻就是我手里拿着一份传单,你要我就给你,由于事先创建对象,所以比较占用资源,上代码。

package single;
public class HungryPerson {
	private static HungryPerson hungryPerson=new HungryPerson();//预先准备对象
	private HungryPerson() {//私有化构造方法
	}
	public static HungryPerson getHungryPerson() {//获取对象方法
		return hungryPerson;
	}
}

测试结果:

141757079
141757079
141757079
141757079
141757079
141757079
141757079
141757079
141757079
141757079

证明饿汉模式线程安全
懒汉模式:
懒汉模式按发传单比喻就是你要传单我就现场给你做,用的时候再创建因此不占用资源,上代码。

package single;
public class LazyPerson {
	private static LazyPerson lazyPerson;//声明属性
	private LazyPerson(){//私有化构造方法	
	}
	public static LazyPerson getLazyPerson() {
		if(null==lazyPerson) {
		lazyPerson = new LazyPerson();//如果之前没创建则创建一个
		}
		return lazyPerson;//返回对象
	}
}

测试结果:
876349272
1141021789
1721087309
1141021789
876349272
1141021789
1141021789
1141021789
1141021789
1141021789
说明线程不安全,那就改进一下吧
懒汉模式(仅新建对象代码加锁):
但是不管是在get方法上加锁还是给代码加锁(对象创建大概率会有初始化代码)都会影响性能,所以我们直接给创建对象的那一段代码加锁,上代码。

package single;
public class LazyPersonNew {
	private static LazyPersonNew lazyPersonNew;//声明属性
	private LazyPersonNew(){//私有化构造方法
	}
	public static LazyPersonNew getLazyPerson() throws InterruptedException {
		if(null==lazyPersonNew) {
			synchronized (LazyPersonNew.class) {
				lazyPersonNew = new LazyPersonNew();//如果之前没创建则创建一个
			}
		}
		return lazyPersonNew;//返回对象
	}
}

测试结果:

141757079
141757079
141757079
141757079
141757079
1796851831
141757079
475341210
141757079
141757079

线程又不安全了,再改进一下
DCL双重检查锁机制:
既然锁跳过了为空判断导致线程不安全,那我们就在锁里面再做个判断,这样线程就安全了

package single;
public class LazyPersonNew {
	private static LazyPersonNew lazyPersonNew;//声明属性
	private LazyPersonNew(){//私有化构造方法
	}
	public static LazyPersonNew getLazyPersonNew() throws InterruptedException {
		if(null==lazyPersonNew) {
			synchronized (LazyPersonNew.class) {
				if(null == lazyPersonNew) {
					lazyPersonNew = new LazyPersonNew();//如果之前没创建则创建一个
				}
			}
		}
		return lazyPersonNew;//返回对象
	}
}

测试结果:

876349272
876349272
876349272
876349272
876349272
876349272
876349272
876349272
876349272
876349272

完美
注:尽量不要加同步锁,同步锁非常影响性能,如果要加最好尽可能减少其影响范围。

猜你喜欢

转载自blog.csdn.net/qq_42695926/article/details/83754234