线程同步加锁在class类上 跟 单例模式
线程同步加锁在class类上 和 单例模式
1 理解下单例模式中 两个 if(null == instance)的判断存在的原因
2 理解下载 .class上加锁的写法(对于没法使用实例对象加锁的,比如下面类是单例类,只能在 .class中加锁)
/** * 单例设计模式:确保一个类只有一个对象 * @author Administrator * */ public class SynDemo02 { /** * @param args */ public static void main(String[] args) { JvmThread thread1 = new JvmThread(100); JvmThread thread2 = new JvmThread(500); thread1.start(); thread2.start(); } } class JvmThread extends Thread{ private long time; public JvmThread() { } public JvmThread(long time) { this.time =time; } @Override public void run() { System.out.println(Thread.currentThread().getName()+"-->创建:"+Jvm.getInstance(time)); } } /** * 单例设计模式 * 确保一个类只有一个对象 * 懒汉式 double checking * 1、构造器私有化,避免外部直接创建对象 * 2、声明一个私有的静态变量 * 3、创建一个对外的公共的静态方法 访问该变量,如果变量没有对象,创建该对象 */ class Jvm { //声明一个私有的静态变量 private static Jvm instance =null; //构造器私有化,避免外部直接创建对象 private Jvm(){ } //创建一个对外的公共的静态方法 访问该变量,如果变量没有对象,创建该对象 public static Jvm getInstance(long time){ //2 然后线程 c d e 进来访问,此时a线程已经完成instance的实例化,因此 c d e 现在在这个if判断中直接跳出得到instance对象, 这就是这个if判断存在的作用 if(null==instance){ // //1 a b线程先过来,此时instance为Null,然后a b线程进来,假如a线程先获取到锁,进入后进行创建instance对象,然后释放锁,然后b线程进来,此时的if(null==instance )判断成功让b线程直接获取a已经创建好的实例返回,这就是这个if判断的作用 synchronized(Jvm.class){ if(null==instance ){ try { Thread.sleep(time); //延时 ,放大错误 ,即使不设置这个延迟,在实际中 创建对象也会有延迟。 } catch (InterruptedException e) { e.printStackTrace(); } instance =new Jvm(); } } }//a return instance; } public static Jvm getInstance3(long time){ //a b c d e -->效率不高, 任何时候多线程过来都需要等待,存在对象也需要等待 synchronized(Jvm.class){ if(null==instance ){ try { Thread.sleep(time); //延时 ,放大错误 } catch (InterruptedException e) { e.printStackTrace(); } instance =new Jvm(); } return instance; } } public static synchronized Jvm getInstance2(long time){ if(null==instance ){ try { Thread.sleep(time); //延时 ,放大错误 } catch (InterruptedException e) { e.printStackTrace(); } instance =new Jvm(); } return instance; } public static Jvm getInstance1(long time){ if(null==instance ){ try { Thread.sleep(time); //延时 ,放大错误 } catch (InterruptedException e) { e.printStackTrace(); } instance =new Jvm(); } return instance; } }