下面这个程序比较经典,现在忘了. 先保存下来.
1 import java.util.ArrayList; 2 3 public final class SingletonObject { 4 private static SingletonObject obj; 5 private SingletonObject(){} 6 //如果在方法上声明同步,会成为系统并发访问的瓶颈 7 public static SingletonObject getInst(){ 8 if(obj == null){ 9 synchronized("aa"){ 10 if(obj == null){ 11 obj = new SingletonObject(); 12 } 13 } 14 } 15 return obj; 16 } 17 18 //1.将对象声明到类中作为类变量,初始化 19 //违反了第一条 20 //2.1.将对象声明到类中作为类变量,且不初始化 21 //在static中初始化 22 //总要有一个初始化的代码,写到哪里?如果写到static代码块中,那么类加载时,就会被执行,和直接写obj2 = ....一样的 23 //上述方案违反了下面的第一条 24 //2.2.将对象声明到类中作为类变量,且不初始化 25 //将初始化写入到获取对象的方法中 26 //obj2 = new SingletonObject(); 27 //上述方案违反了下面的第二条 28 //2.2.1.将对象声明到类中作为类变量,且不初始化 29 //在获取方法中进行null的判定,进行初始化 30 //上述方案违反了下面的第三条 31 //最终方案:既要进行对象的一次初始化,又不能将该初始化语句放入到获取方法中 32 //Java中哪种方案是归属于类的模型体系下的且只执行一次,且在类加载时不进行加载,但是使用时才进行加载,那么这个方案就是最终方案 33 //内部类解决方案 34 35 private static class Inner{ 36 //将对象初始化的操作加入到内部类中 37 private static final SingletonObject obj2 = new SingletonObject(); 38 } 39 40 public static SingletonObject getInst2(){ 41 //既需要延迟加载,不使用不创建 42 //又要保障创建的时候不会被多次创建,做成单例 43 //又要求每次获取的时候最好不做null判定 44 return Inner.obj2; 45 } 46 47 public static void main2(String[] args) { 48 System.out.println(SingletonObject.getInst()); 49 System.out.println(SingletonObject.getInst()); 50 System.out.println(SingletonObject.getInst()); 51 } 52 53 public static void main(String[] args) { 54 55 long t1 = System.currentTimeMillis(); 56 long start = 90000000000000001L; 57 long end = 90000000000000100L; 58 long refMax = (long)Math.sqrt(end); 59 ArrayList<Long> primes = new ArrayList<Long>(); 60 OUT: 61 for(long i = 2;i <= refMax ; i++){ 62 for(long j = 2;j<= Math.sqrt(i);j++){ 63 if(i % j == 0){ 64 continue OUT; 65 } 66 } 67 primes.add(i); 68 } 69 System.out.println("end"); 70 OUT: 71 for(long i = start;i<=end;i++){ 72 for(Long prime:primes){ 73 if(i % prime == 0){ 74 continue OUT; 75 } 76 } 77 System.out.print(i+" "); 78 } 79 long t2 = System.currentTimeMillis(); 80 System.out.println(t2-t1); 81 82 83 OUT: 84 for(int i = 101;i <= 200 ; i++){ 85 for(int j = 2;j<= Math.sqrt(i);j++){ 86 if(i % j == 0){ 87 continue OUT; 88 } 89 } 90 System.out.print(i+" "); 91 } 92 } 93 } 94 /* 95 A走到这里,时间片到期,该B运行 96 B执行完毕了,此时obj对象是B线程new出来的 97 此时B执行完毕,A又运行,由于是从此处时间片到期,恢复运行后,还从当前行继续 98 执行下面的代码,A线程又创建了一个对象 99 此时B创建了一次,A创建了一次,外面最少是两个对象 100 */