第四个周末-不纠结-一个BUG引发的思考


纠结使人浮躁,但是纠结也使人进步。黎明前的黑暗,熬过去就是光明的来临。熬不过去就是黑暗的沉沦。

下面的一段的代码会引起一个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 toids) { this.toids = toids; } ~~~

下面的一个例子可以更加清晰的说明问题:

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);
	}
}

我们操作的是一个地址的复制,现在是这么理解的,具体在栈帧中是如何存储的,我们继续的探究。



上一篇  第五个周末-沉下心来 下一篇   第三个周末