单例设计模式,确保了一个类只有一个对象,也就是不会提供对外公开的构造方法
创建对象在类的内部进行,对外只提供一个共有的访问对象的方法
单例设计模式又有懒汉式,和饿汉式
懒汉式:
懒汉式的设计有两个要点
1.double-check的作用在于提高效率,在线程对象访问这个方法时,先判断是否有实例Jvm对象,这样当t1线程已经创建了Jvm对象以后,t2线程就可以直接返回这个Jvm对象了
2.synchronized的同步块中的锁定资源为对象是,就可以将参数设置为(this)
但是这里锁定的静态资源,这里就需要用到(Jvm.class)
/**
* 懒汉式
* 1.构造器私有化,避免外部直接创建对象
* 2.声明私有静态变量
* 3.创建一个对外公共的静态方法,访问该对象
* @author wwyDEPP
*
*/
class Jvm{
private static Jvm instance=null;
private Jvm(){}
public static Jvm getInstance(long time) {
//double-check 提高效率,提供已经存在对象的访问效率
if (null == instance) {
synchronized (Jvm.class) {
if (null == instance) {//确保安全
try {
Thread.sleep(time);// 延时,放大错误发生概率
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
instance = new Jvm();
}
}
}
return instance;
}
}
饿汉式:
饿汉式相对简单,由于它在声明静态私有属性的同时就创建了对象,所以避免了线程安全
因为在类加载的时候就已经把对象创建好了,而类只加载一次
为了提高效率,将静态私有属性放在内部类中,这样当Jvm2这个类加载时,会加载这个类的所有属性和方法,
只有使用getInstance方法的时候,才会加载Jvmholder类,类只有在使用的时候才会加载
/**
* 饿汉式
* 1.构造器私有化,避免外部直接创建对象
* 2.声明私有静态变量,创建对象
* 3.创建一个对外公共的静态方法
*/
class Jvm2{
//类在使用的时候加载,使用内部类延缓了加载时间
private static class Jvmholder{
private static Jvm2 instance=new Jvm2();
}
private Jvm2(){}
public static Jvm2 getInstance(){
return Jvmholder.instance;
}
}
测试上述两个类
public class SynDemo02 {
public static void main(String[] args) {
JvmThread t1=new JvmThread(100);
JvmThread t2=new JvmThread(200);
t1.start();
t2.start();
}
}
class JvmThread extends Thread{
private long time;
@Override
public void run(){
System.out.println(Thread.currentThread().getName()+"--creat"+Jvm2.getInstance());
}
public JvmThread(long time){
this.time=time;
}
}
输出结果为:
Thread-1--creatthread.Jvm2@2e6e1408
Thread-0--creatthread.Jvm2@2e6e1408
可见,两个线程对象对应的是用一个对象,如果不使用synchronized关键字,则还是会创建两个不同的对象
那就不符合单例模式的要求了
Jvm类中添加线程休眠,也只是为了放大错误,容易看出是创建了两个不同对象