一道数学累加问题

时间:2022-08-06 19:28:57

这里有一道面试题目:

创建5个线程,实现整数0加到1000,然后输出结果。

咋一看,也没什么特别的地方,很简单的。就实现如下了:

package multiProc;

public class threadEx extends Thread {
public static int tNum=0;
public static int totalNum=0;
private String name;
public threadEx(String name) {
super();
this.name = name;
}

public synchronized void run() {
for(;tNum <=1000;tNum++) {
totalNum+=tNum;
System.out.println( this.name +"线程执行:" + "tNum=" + tNum+" 总和="+totalNum);
}
}
public static void main(String[] args) {
threadEx m1=new threadEx("线程a");
threadEx m2=new threadEx("线程b");
threadEx m3=new threadEx("线程c");
threadEx m4=new threadEx("线程d");
threadEx m5=new threadEx("线程e");

m1.start();
m2.start();
m3.start();
m4.start();
m5.start();
}
}

回来我就在自己电脑上把代码给敲出来,跑了一下。可是结果却令我失望了,截图如下:一道数学累加问题

一道数学累加问题

一道数学累加问题

明显结果错误了,于是我又试了开单线程、双线程,结果都没问题,输出正确,截图如下:

一道数学累加问题

一道数学累加问题

一道数学累加问题

但是,三线程条线下又是出错的,偶尔会正确,截图如下:

一道数学累加问题

线程a线程执行:tNum=998 总和=399648
线程a线程执行:tNum=999 总和=400647
线程a线程执行:tNum=1000 总和=401647
线程c线程执行:tNum=457 总和=11247
线程b线程执行:tNum=494 总和=88248

一道数学累加问题

那么,为什么在小于3的情况下,输出结果是正确的,而在线程数大于等于3的时候结果就偏离正确结果了呢?

我怀疑是不是CPU线程调度的问题啊?

查看了一下,我的CPU是双核双线程,按道理讲如果是因为CPU线程调度的问题的话,那么在三线程条件下,为什么没有出错呢?所以也就基本排除了这一假设。

那到底是为什么呢?

我将start()改成run(),运行结果正确,但是没有了多线程运行计算的效果。

线程a线程执行:tNum=993 总和=493521
线程a线程执行:tNum=994 总和=494515
线程a线程执行:tNum=995 总和=495510
线程a线程执行:tNum=996 总和=496506
线程a线程执行:tNum=997 总和=497503
线程a线程执行:tNum=998 总和=498501
线程a线程执行:tNum=999 总和=499500
线程a线程执行:tNum=1000 总和=500500

一道数学累加问题

查了下网络,start()与run()的区别如下:

run()是Runnable接口中定义的一个方法,是为了让客户程序员在这个方法里写自己的功能代码的。直接调用和普通的类调用自己的成员方法是没有任何区别的。而start()则是线程开始运行的标志,当这个方法被调用后,程序中才会多出一个独立的线程,接着便是执行run()方法。与运行结果相符。

头疼啊!

我尝试给累加的字段加锁,但还是无济于事。

后来在QQ群里一个哥们无意的建议让事情有了转机。将tNum的修饰符static去掉试试。

果然,问题解决!原来是我的参量声明问题,多线程没那么复杂。庆贺啊 ~

但新的问题也出来了,JAVA线程对于静态成员变量有特殊处理吗?留着往后再深究吧。