单例模式:一个类模板中,在整个系统运行过程中,只允许产生一个实例(有且只有一个)。
保证单例的技术:
饿汉式:在实例使用之前,不管用不用,都先new出来,避免了线程安全问题。
特点:它是在类加载的时候立即初始化,并创建对象。
优点:没有任何的锁,执行效率高。
缺点:类加载的时候就创建对象。浪费了内存,占着茅坑不拉屎。
例子:
/**
* 饿汉式单例
* Created by zwz on 2018/9/4.
*/
public class Hungry {
private Hungry(){
}
private static final Hungry hungry = new Hungry();
public static Hungry getInstance(){
return hungry;
}
}
懒汉式:默认加载时不实例化,在需要时才实例化(延时加载)。
第一种:线程不安全的懒汉式单例:
/**
* 懒汉式单例(线程不安全)
* Created by zwz on 2018/9/4.
*/
public class LazyOne {
private LazyOne(){}
private static LazyOne lazyOne = null;
public static LazyOne getInstance(){
if(lazyOne == null){
//可能多个线程同时进来创建多个对象
lazyOne = new LazyOne();
}
return lazyOne;
}
}
编写一个测试线程安全类:
package patterns.singleton.test;
import patterns.singleton.hungry.Hungry;
import patterns.singleton.lazy.LazyOne;
import java.util.concurrent.CountDownLatch;
/**
* 线程安全测试
* Created by zwz on 2018/9/4.
*/
public class ThreadSafeTest {
public static void main(String[] args) {
int count = 300;
//发令枪
final CountDownLatch latch = new CountDownLatch(count);
long start = System.currentTimeMillis();
for(int i = 0; i< count;i++){
new Thread(){
@Override
public void run(){
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
Object obj = LazyOne.getInstance();
System.out.println(obj);
}
}.start();
latch.countDown();
}
long end = System.currentTimeMillis();
System.out.println("