工厂模式——单例模式
一.单例模式介绍:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
二. 单例模式分为:
-
懒汉式单例模式(并不是线程安全的)
-
饿汉式单例模式
1.饿汉式单例模式
class MySingleTon4{ private static MySingleTon4 sigleTon4 =new MySingleTon4(); private MySingleTon4(){ System.out.println("MySingleTon().init"); } public static MySingleTon4 getInstance() { return sigleTon4; } }
2.懒汉式单例模式
(1).
单线程安全的(但是多线程时,当一个new完而还没有赋值时,有N个线程同时进来,这时,singleTon5的值还是为空的,这N个线程也会开辟内存空间,new一个对象)
class MySingleTon5{ private static MySingleTon5 singleTon5=null; private static Object lock=new Object(); private MySingleTon5(){ System.out.println("MySingleTon5.init"); } private static MySingleTon5 getSingleTon5(){ if(singleTon5==null){ singleTon5=new MySingleTon5(); } return singleTon5; } }
(2).
给每个进来的线程都加上锁,这样对于多线程来说是安全的
但是对于单线程来说,它就一个线程给它加上锁会消耗资源的class MySingleTon5{ private static MySingleTon5 singleTon5=null; private static Object lock=new Object(); private MySingleTon5(){ System.out.println("MySingleTon5.init"); } private static MySingleTon5 getSingleTon5(){ synchronized (lock){ if(singleTon5==null){ singleTon5=new MySingleTon5(); } } return singleTon5; } }
(3).
线程是安全的,但是第一个线程进来的时候,判断为空然后加上锁,当它new完之后,如果还没有来得及赋值,这时有第二个进程来,此时的singleTon5==null,所以会进来给第二个加上锁,等待第一个执行完的时候 ,解锁,虽然singleTon5不为空,但是第二个已经加上锁了。第二个也会new一个内存出来,所以至少要执行两次
class MySingleTon5{ private static MySingleTon5 singleTon5=null; private static Object lock=new Object(); private MySingleTon5(){ System.out.println("MySingleTon5.init"); } private static MySingleTon5 getSingleTon5(){ if(singleTon5==null){ synchronized (lock){ singleTon5=new MySingleTon5(); } } return singleTon5; } }
(4)双重检验
这是最优的线程安全(即使用于单线程又适用于多线程)第一个进来的时候,判断为空,然后加锁,继续判断为空,如果开辟了空间之后,还没有去赋值,这时候有其他线程进来,此时singleTon5==null,加上锁,然后等第一个执行完毕之后,其他有锁的会判断singleTon5,不为空,然后就不会执行下面的,然后解锁
class MySingleTon5{
private static MySingleTon5 singleTon5=null;
private static Object lock=new Object();
private MySingleTon5(){
System.out.println("MySingleTon5.init");
}
private static MySingleTon5 getSingleTon5(){
if(singleTon5==null){
synchronized (lock){
if(singleTon5==null){
singleTon5=new MySingleTon5();
}
}
}
return singleTon5;
}
}