作者:麦土豆1937 | 来源:互联网 | 2024-12-20 11:49
在编程面试中,遇到一个有趣的多线程问题:利用五个线程完成从0到1000的整数累加,并输出最终结果。初看之下,这似乎是一个简单的任务。然而,在实际编码过程中却发现了一些意想不到的问题。
原始代码如下:
```java
package multiProc;
public class ThreadExample extends Thread {
private int tNum = 0;
private static int totalSum = 0;
private String threadName;
public ThreadExample(String name) {
this.threadName = name;
}
@Override
public synchronized void run() {
while (tNum <= 1000) {
totalSum += tNum;
System.out.println(threadName + "执行: tNum=" + tNum + " 总和=" + totalSum);
tNum++;
}
}
public static void main(String[] args) {
ThreadExample t1 = new ThreadExample("线程A");
ThreadExample t2 = new ThreadExample("线程B");
ThreadExample t3 = new ThreadExample("线程C");
ThreadExample t4 = new ThreadExample("线程D");
ThreadExample t5 = new ThreadExample("线程E");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
```
在测试过程中发现,当使用三个或更多线程时,输出的结果经常出现错误。例如,某次测试结果显示,线程A执行到tNum=1000时总和为401647,而实际上应该为500500。这种偏差让人困惑。
经过一系列测试,包括单线程、双线程的情况,发现它们都能正常工作并返回正确的结果。但在三线程及以上的配置下,结果则不稳定,有时正确,有时错误。
初步怀疑是由于CPU线程调度机制导致的问题。考虑到计算机的CPU是双核双线程,理论上应该能够良好地支持多线程操作。进一步探究发现,即使在三线程条件下,问题也不总是出现,这表明CPU调度并不是根本原因。
尝试将`start()`方法改为直接调用`run()`方法,虽然得到了正确的结果,但这失去了多线程的意义,因为此时所有计算都在主线程中进行。
查阅资料了解到,`start()`方法用于启动新线程,而`run()`方法只是普通的方法调用,不会创建新线程。因此,直接调用`run()`并不会实现真正的并发。
为了确保线程安全,对累加操作进行了同步处理,但问题依旧存在。最终,在社区的帮助下,移除了`tNum`的`static`修饰符,问题得以解决。
这个问题揭示了Java中静态变量在多线程环境下的特殊行为,即静态变量被所有线程共享,若未妥善管理可能会引发数据竞争。此案例不仅解决了当前的问题,也为后续深入理解Java多线程编程打下了基础。