单例 设计模式:
确保一个类在内存中只有一个对象
- 禁止类外建立该类对象——类外不能new 对象
- 在本类中定义一个对象,
- 对外提供方法,以实现其他类对本类内对象的访问
------->
- 将构造函数私有化
- 在类内创建本类私有对象
- 在类内提供公有方法获取该对象
class Single
{
//饿汉式:类一进内存就建立对象 通常采用此方式
private Single(){}//构造函数私有,外部不可访问,限制此类只能new一个对象
private int num;
public void setNum(int num)
{
this.num=num;
}
public int getNum()
{
return num;
}
private static Single s=new Single();//因为下面的方法的静态,此属性也要静态
public static Single getInstance()
{
return s;
}
}
class SingleDemo
{
public static void main(String[] args)
{
Single s1=Single.getInstance();//s1和类中的s指向同一片内存区域
s1.setNum(20);//s1,s2和类中的s指向同一片内存区域
Single s2=Single.getInstance();
System.out.println(s2.getNum());//此句可证明
}
}
懒汉式
延迟加载——当调用getInstance()方法时,才建立对象
public static Single s=null;
private Single(){}
public static Single getInstance()
{
if(s==null)
{
synchronized (Single.class)
{
if(s==null)
s=new Single();
}
}
return s;
}
懒汉式的对外提供对象的方法中,有两次判断是null的语句。
第一句的目的是判断是否要加锁
第二句的目的是判断手否要为对象初始化。
这种双重验证,适用于多线程的情况。
比如程序刚开始运行,两个线程A,B,同时调用了getInstance()方法,
此时,两个多线程都走到了 第一次判断对象是否为null, 的语句,然后只有一个线程A上了锁。另一个线程B在锁外等候,但已经判断过 对象为null..
线程A又 执行了判断 对象为null, 可以创建对象。释放锁。线程A执行完毕。
此时轮到线程B继续执行,从第5行 后开始执行,此时线程B拿到锁,进行 第7句代码的执行。 而先前线程A已经为对象s进行了创建,所以不再会继续创建对象。线程B释放锁,退出。
——线程等待时会记住等待的点,当得到执行权时,是从等待的点处开始执行,而不会从开头重新执行,
饿汉式与懒汉式的区别,在于类变量开始声明时便指向一个对象还是调用对外方法时才建立对象
运行结果20 , 很好地贯彻了单例设计模式只允许建立一个对象的方针