个人记录:2018年,工作的第6到7个年头。
重点研究自己不太擅长的技术:分布式、高并发、大数据量、数据库优化、高性能、负载均衡等。
刷题是一种态度,是一种好习惯。
问题源头
为什么最后两行没有运行
http://ifeve.com/question/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%9C%80%E5%90%8E%E4%B8%A4%E8%A1%8C%E6%B2%A1%E6%9C%89%E8%BF%90%E8%A1%8C/
import java.util.concurrent.atomic.AtomicInteger;
//http://ifeve.com/question/为什么最后两行没有运行
//面试题 › 为什么最后两行没有运行
public class AutomicDemo {
public static int k = 0;
static AtomicInteger i = new AtomicInteger(0);
public static void main(String[] args) {
for (int m = 0; m < 10; m++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for (int p = 0; p < 4000; p++) {
System.out.println("i:" + i.get());
i.getAndIncrement();
System.out.println("k: " + k);
k++;
}
}
});
t.start();
}
System.out.println("最终i: --------------" + i);
System.out.println("最终k: --------------" + k);
}
}
个人看法
最开始,以为是线程出现死循环,导致最后2行代码不会执行。
但是,看多线程代码,不会死循环。
感觉这道题,更有可能是在考察 多线程安全,i++的原子性,static变量线程不安全。
但是,第1次运行结果,i:39999 k: 39999,有点怀疑人生了。
还是相信自己,可能是单机执行,i++执行太快了,没能复现出来。
又执行了2次,出现了1次k=39783,而i=39999。
验证了自己的判断。
在3次正常运行中,都没有看到最后“最终i: --------------40000”和“最终k: --------------40000”之类的输出结果。
还以为真没有执行呢?
这个根本不可能,平时多线程demo最经常的句式就是程序中的那样,最后打印结束。
不可能没有运行,不可能不打印结果。
但是,题目非要说没有运行,真是操蛋,瞎说,误导人民群众。
只好拿出程序员绝技,debug。
最后1行,加了断点,在最后一行输出了“最终...”。
比较纳闷,为啥debug的时候,会在最后一行呢?
想明白了,主线程卡在断点,子线程正常运行,主线程卡在那里的时候,k和i的值,一直在不断变化。
正常运行的时候,“最终...”正常打印了,被其它打印结果覆盖了。
哎哟。
运行3次结果
------1次----------
i:39998
k: 39782
i:39999
k: 39783
------2次------------
i:39997
k: 39997
i:39998
k: 39998
i:39999
----debug2次结果------------
k: 39995
i:39996
k: 39996
i:39997
k: 39997
i:39998
k: 39998
i:39999
k: 39999
最终i: --------------40000
最终k: --------------40000
i:39998
k: 39995
i:39999
k: 39996
最终i: --------------40000
最终k: --------------39997
网友观点
一、看来只有我一个人傻傻的把代码贴到eclipse里分析
不是没执行,是缓冲区有限,后面打印的把前面的冲掉了
把循环次数从4000改为4,或者命令行执行 java AtomicDemo >> /tmp/result 然后看result中的内容就知道了
二、main线程先于子线程结束了。最后两句前面应该调用所有子线程的join()
重点研究自己不太擅长的技术:分布式、高并发、大数据量、数据库优化、高性能、负载均衡等。
刷题是一种态度,是一种好习惯。
问题源头
为什么最后两行没有运行
http://ifeve.com/question/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%9C%80%E5%90%8E%E4%B8%A4%E8%A1%8C%E6%B2%A1%E6%9C%89%E8%BF%90%E8%A1%8C/
import java.util.concurrent.atomic.AtomicInteger;
//http://ifeve.com/question/为什么最后两行没有运行
//面试题 › 为什么最后两行没有运行
public class AutomicDemo {
public static int k = 0;
static AtomicInteger i = new AtomicInteger(0);
public static void main(String[] args) {
for (int m = 0; m < 10; m++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for (int p = 0; p < 4000; p++) {
System.out.println("i:" + i.get());
i.getAndIncrement();
System.out.println("k: " + k);
k++;
}
}
});
t.start();
}
System.out.println("最终i: --------------" + i);
System.out.println("最终k: --------------" + k);
}
}
个人看法
最开始,以为是线程出现死循环,导致最后2行代码不会执行。
但是,看多线程代码,不会死循环。
感觉这道题,更有可能是在考察 多线程安全,i++的原子性,static变量线程不安全。
但是,第1次运行结果,i:39999 k: 39999,有点怀疑人生了。
还是相信自己,可能是单机执行,i++执行太快了,没能复现出来。
又执行了2次,出现了1次k=39783,而i=39999。
验证了自己的判断。
在3次正常运行中,都没有看到最后“最终i: --------------40000”和“最终k: --------------40000”之类的输出结果。
还以为真没有执行呢?
这个根本不可能,平时多线程demo最经常的句式就是程序中的那样,最后打印结束。
不可能没有运行,不可能不打印结果。
但是,题目非要说没有运行,真是操蛋,瞎说,误导人民群众。
只好拿出程序员绝技,debug。
最后1行,加了断点,在最后一行输出了“最终...”。
比较纳闷,为啥debug的时候,会在最后一行呢?
想明白了,主线程卡在断点,子线程正常运行,主线程卡在那里的时候,k和i的值,一直在不断变化。
正常运行的时候,“最终...”正常打印了,被其它打印结果覆盖了。
哎哟。
运行3次结果
------1次----------
i:39998
k: 39782
i:39999
k: 39783
------2次------------
i:39997
k: 39997
i:39998
k: 39998
i:39999
----debug2次结果------------
k: 39995
i:39996
k: 39996
i:39997
k: 39997
i:39998
k: 39998
i:39999
k: 39999
最终i: --------------40000
最终k: --------------40000
i:39998
k: 39995
i:39999
k: 39996
最终i: --------------40000
最终k: --------------39997
网友观点
一、看来只有我一个人傻傻的把代码贴到eclipse里分析
不是没执行,是缓冲区有限,后面打印的把前面的冲掉了
把循环次数从4000改为4,或者命令行执行 java AtomicDemo >> /tmp/result 然后看result中的内容就知道了
二、main线程先于子线程结束了。最后两句前面应该调用所有子线程的join()