一 面试题
1 举例栈溢出的情况?
栈溢出:*Error。
main 函数递归调用 main 函数会出现栈溢出。
可以通过 -Xss 设置栈的大小。
2 调整栈大小,就能保证不出现溢出么?
不能保证不溢出,调大一些,只是出现得晚一些。比如:main 函数递归调用 main 函数,一定会出现栈溢出。
3 分配的栈内存越大越好么?
不是,一定时间内降低了 OOM 概率,但是会挤占其它的线程空间,因为整个空间是有限的。
4 垃圾回收是否涉及到虚拟机栈?
不会
5 方法中定义的局部变量是否线程安全?
具体问题具体分析。见实战中的代码分析。
6 运行时数据区,是否存在Error和GC?
二 实战
1 代码分析
/**
* 面试题:
* 方法中定义的局部变量是否线程安全?具体情况具体分析
* 何为线程安全?
* 如果只有一个线程才可以操作此数据,则必是线程安全的。
* 如果有多个线程操作此数据,则此数据是共享数据。如果不考虑同步机制的话,会存在线程安全问题。
*/
public class StringBuilderTest {
int num = 10;
// s1的声明方式是线程安全的
public static void method1() {
// StringBuilder : 这个类是线程不安全
// StringBuffer : 这个类是线程安全,两个类的区别是 StringBuffer 中的方法加了 synchronized
StringBuilder s1 = new StringBuilder();
s1.append("a");
s1.append("b");
//...
}
// sBuilder 的操作过程:是线程不安全的,因为 sBuilder 是从函数外传递进来的,成了共享数据
public static void method2(StringBuilder sBuilder) {
sBuilder.append("a");
sBuilder.append("b");
//...
}
// s1 的操作:是线程不安全的,因为 s1 传递到函数外了,成了共享数据
public static StringBuilder method3() {
StringBuilder s1 = new StringBuilder();
s1.append("a");
s1.append("b");
return s1;
}
// s1 的操作:是线程安全的
public static String method4() {
StringBuilder s1 = new StringBuilder();
s1.append("a");
s1.append("b");
return s1.toString();
}
public static void main(String[] args) {
StringBuilder s = new StringBuilder();
new Thread(() -> {
s.append("a");
s.append("b");
}).start();
method2(s);
}
}
2 代码说明
总结一句话就是:如果对象是在内部产生,并在内部消亡,没有返回到外部,那么它就是线程安全的,反之则是线程不安全的。