但是volatile不能保证原子性,也就不能保证线程安全。
1,可见性
可见性指的是在一个线程中对该变量的修改会马上由工作内存(Work Memory)写回主内存(Main Memory),所以会马上反应在其它线程的读取操作中。顺便一提,工作内存和主内存可以近似理解为实际电脑中的高速缓存和主存,工作内存是线程独享的,主存是线程共享的。
2,禁止指令重排序优化
禁止指令重排序优化。大家知道我们写的代码(尤其是多线程代码),由于编译器优化,在实际执行的时候可能与我们编写的顺序不同。编译器只保证程序执行结果与源代码相同,却不保证实际指令的顺序与源代码相同。这在单线程看起来没什么问题,然而一旦引入多线程,这种乱序就可能导致严重问题。volatile关键字就可以从语义上解决这个问题。
题目说抛出一个异常,但是没说具体是什么异常,那么就要分情况了:
1.如果抛出一个FileNotFoundException(或其子类),那么最终结果就打印FileNotFoundException
2.如果抛出一个IOException,或者IOException的子类(不包含FileNotFoundException及其子类),那么最终结果就打印IOException
3.如果抛出一个Exception(不包含IOException及其子类),那么最终结果就打印Exception.
以上,所以3个皆有可能.但是,不管是哪一种情况,只会输出其中之一。
从答案上来看,B,C,D的输出情况是不存在的。因此选A
- 粉红色的是受检查的异常(checked exceptions),其必须被 try{}catch语句块所捕获,或者在方法签名里通过throws子句声明.受检查的异常必须在编译时被捕捉处理,命名为 Checked Exception 是因为Java编译器要进行检查,Java虚拟机也要进行检查,以确保这个规则得到遵守.
- 绿色的异常是运行时异常(runtime exceptions),需要程序员自己分析代码决定是否捕获和处理,比如 空指针,被0除…
- 而声明为Error的,则属于严重错误,如系统崩溃、虚拟机错误、动态链接失败等,这些错误无法恢复或者不可能捕捉,将导致应用程序中断,Error不需要捕捉。
import java.util.*;
public class Main3 {
public int[] exchangeAB(int[] AB) {
AB[0] = AB[0]-AB[1];
AB[1] = AB[0]+AB[1];
AB[0] = AB[1]-AB[0];
return AB;
}
}
import java.util.*;
public class Main4 {
public String[] getGray(int n) {
if(n==1){
return new String[]{"0","1"};
}
String[] s1=getGray(n-1);//递归调用
String[] s2=new String[2*s1.length];
for(int i=0;i<s1.length;i++){
s2[i]="0"+s1[i];//首位添加0
s2[i+s1.length]="1"+s1[s1.length-1-i];//首位添加1,注意需要顺序反向
}
return s2;
}