问题描述
- 有一道Java面试题,没太理解明白,求大神指点啊~
-
package test2;
/**- 设计4个线程,其中两个线程每次对i增加1,另外两个线程对i每次减少1
- @author liuyu
*
*/
public class Test {private int i ;
private synchronized void inc(){
i ++;
System. out .println(Thread.currentThread().getName()+ "--inc--" + i );
}
private synchronized void dec(){
i --;
System. out .println(Thread.currentThread().getName()+ "--dec--" + i );
}
class Inc implements Runnable {
public void run() {
inc();
}
}
class Dec extends Thread{
public void run() {
dec();
}
}
public static void main(String[] args) {
Test t = new Test();
Inc inc = t. new Inc();
Thread thread = null;
// 创建 2 个增加线程
for ( int i = 0; i < 2; i++) {
thread = new Thread(inc);
thread.start();
}
// 创建 2 个减少线程
for ( int i = 0; i < 2; i++) {
thread = t.new Dec();
thread.start();
}
}
}
输出:Thread-0--inc--1
Thread-3--dec--0
Thread-2--dec---1
Thread-1--inc--0可是我感觉应该输出是:
Thread-0--inc--1
Thread-1--inc--2
Thread-2--dec--1
Thread-3--dec--0因为按照执行顺序,当执行第一个for循环第一次的时候创建第一个线程,并且i加1,执行第二次for循环的时候i再加1等于2;
执行第二个for循环的时候,创建第三个线程,并且i减1,执行第二次的后事i再减1等于0为什么不对呢?
解决方案
卤煮的想法没错,程序确实是一步一步从上往下执行的,也创建了四个线程,之所以没有出现预期的结果,可能是有一点被忽略了,java中的线程有自己的生命周期,一个新的线程会经历创建、就绪然后才能进入执行状态。也就是说你的程序创建了四个线程,它们只是进入了就绪状态,等待cpu线程栈的调度,而何时可以得执行以及执行的顺序还要依赖cpu的性能、cpu的个数等等。所以程序的输出结果应该是未知的,卤煮可以多跑几次,应该会输出不同内容。嘿嘿。
解决方案三:
这是不是跟线程状态有关系呢?
你只是把线程start了,并不是直接计算了,可能当时线程并没有开始计算。
如果多调用几次应该每次结果都不一样吧?
我只是提供个思路,毕竟我也不是很清楚。sorry
解决方案四:
这个你应该能搜到,讲解的就是java的线程同步问题,很经典的套路
解决方案五:
我知道例子,我想问的是 为什么每次执行结果顺序不一样呢?我想问的是这个 ,继续求解答,,
解决方案六:
四个线程的启动可以认为是同时发生的(间隔时间非常短),线程并发并不代表线程会同时执行(可以百度下并发和并行的区别)。
CPU个数是限制,例如在单核CPU上,同一时间只能将cpu分配给某一个线程执行,这就是所谓的资源竞争,而竞争的结果不一定是相同的。
所以四个线程执行顺序不可预期。
解决方案七:
cpu执行哪个,是有时间片的,虽然创建了一个线程,但是线程并不一定会立即被cpu运行,所以可能在等待时间片。
所以也不一定结果就是 1 0 1 0,也有可能是 1 2 1 0
你要想输出结果一定,就需要做线程的同步,保证某个线程先执行,另外一个线程再执行
解决方案八:
是的,从程序流程来看,该是你说的结果。但是,线程创建、启动后,并不是马上就执行你的业务逻辑,至于哪个先执行,是需要进行调度的,由于不确定性,结果也是会不一样的。可以借助线程的join()或者优先级等,来提高优先执行顺序,以达到预期效果。