大家好我有这段代码:
public class ThreadTester {
public static void main(String args[]) {
Counter c = new Counter();
for (int i = 0; i < 10; i++) {
MyThread a = new MyThread(c);
MyThread b = new MyThread(c);
a.start();
b.start();
}
System.out.println("The value of the balance is " + c.getVal());
}
}
class MyThread extends Thread {
private Counter c;
public MyThread(Counter c){ this.c = c; }
public void run(){ s.increment(); }
}
class Counter {
private int i = 100;
public synchronized void increment(){ i++; }
public synchronized int getVal(){ return i; }
}
现在我认为这应该给出120的期望结果 - 但是结果似乎在115和120之间波动。如果我在Thread.sleep(1)
之后添加b.start()
我总是得到所需的结果120为什么会这样?
这让我很困惑,我很感激能得到的任何帮助,谢谢
答案 0 :(得分:3)
在启动所有线程后打印计数器的值,而不是在所有线程完成之后打印。
在已经开始等待它们完成的所有线程上使用Thread.join(),然后打印该值。或者使用CountDownLatch。睡觉会意外地给你正确的结果。它允许所有线程完成,但仅仅因为他们只有很少的事情要做,睡眠1毫秒就足够了。
答案 1 :(得分:1)
因为线程并行运行。
在一个或多个其他线程增加之前,您正在主线程中打印c.getVal()
。
当你睡觉时,你允许其他线程有足够的时间来完成,然后打印。
答案 2 :(得分:0)
因为到达System.out时并非所有线程都完成了增量任务。注入睡眠允许线程在到达输出之前完成。
答案 3 :(得分:0)
原因:
第三个线程(执行main()
)函数在以随机顺序启动线程a和b之后立即进入以下语句,这就是为什么会得到不可预测的结果。
System.out.println("The value of the balance is " + c.getVal());
下一个问题:
如果我在b.start()之后添加一个Thread.sleep(1),我总会得到120的预期结果。为什么会这样?
这是因为您停止主线程足够长(在CPU世界中1秒是很长时间)以允许线程a和b完成。
解决方案:使主线程等待,直到线程a和b都完成。一种方式:
Counter c = new Counter();
for (int i = 0; i < 10; i++) {
MyThread a = new MyThread(c);
MyThread b = new MyThread(c);
a.start();
b.start();
}
a.join(); // wait for thread a to finish
b.join(); // wait for thread b to finish
System.out.println("The value of the balance is " + c.getVal());
答案 4 :(得分:0)
您正在线程完成之前打印结果(这就是结果变化的原因)。在打印结果之前,您需要等待所有线程完成。
重新构建main
方法,如下所示:
public static void main(String args[]) {
Counter c = new Counter();
MyThread[] a = MyThread[20];
for (int i = 0; i < 20; i++) {
a[i] = new MyThread(c);
a[i].start();
}
for (int i = 0; i < 20; i++) {
a[i].join();
}
System.out.println("The value of the balance is " + c.getVal());
}
首先,我循环20次,因为你的循环迭代了10次,同时创建了两个线程(所以你也创建了20个线程)。您需要保持引用(通过a
数组),以便主线程可以等到所有线程都完成(使用join
)。完成所有操作后,将返回正确的结果。