纠结使人浮躁,但是纠结也使人进步。黎明前的黑暗,熬过去就是光明的来临。熬不过去就是黑暗的沉沦。
下面的一段的代码会引起一个bug:
public class ClearCollection {
public static void main(String[] args) {
// 巨量的toids,需要1000一次,分批量的处理
List<String> toidsm = new ArrayList<>(10000);
List<String> toids = new ArrayList<>();
for (int i = 0; i < toidsm.size(); i++) {
if(toids.size() < 1000){
toids.add(toidsm.get(i));
}else{
Batch bach = new Batch(toids);
ThreadClass thread = new ThreadClass(bach);
thread.start();
toids.clear();
}
}
}
}
class ThreadClass extends Thread {
Batch bach;
public ThreadClass(Batch bach) {
this.bach = bach;
}
@Override
public void run() {
System.out.println("处理了:"+this.bach.getToids());
}
}
class Batch {
private List<String> toids;
public Batch(List<String> toids2) {
this.toids = toids2;
}
public List<String> getToids() {
return toids;
}
public void setToids(List<String> toids) {
this.toids = toids;
}
}
错误的原因:toids.clear()时候,可能线程还没有执行到: System.out.println(“处理了:”+this.bach.getToids()); 就有可能吧toids里面的东西全部的clear掉,导致错误。
深层次的原因:我们操作的toids到底是什么?Bach类中的这个构造函数:
中的参数是什么?我们在操作toids的时候,到底发生了什么?传入的是值,还是址?还是只是一个副本?
~~~
public Batch(List
下面的一个例子可以更加清晰的说明问题:
public class ChangeValue {
private String value = "a";
public void change(ChangeValue value){
value.value = "b";
}
public void change(String value){
value = "b";
}
public static void main(String[] args) {
ChangeValue value = new ChangeValue();
value.change(value.value);
System.out.println(value.value);
value.change(value);
System.out.println(value.value);
}
}
我们操作的是一个地址的复制,现在是这么理解的,具体在栈帧中是如何存储的,我们继续的探究。