在面试的时候遇到一个问题,问如下程序的输出结果是啥
public static void main(String[] args) {
int count = 0;
for (int i = 0; i < 10; i++) {
count = count++;
}
System.out.println(count);
}
结果是0;有木有很意外。
1>自增的两种方式,第一种是count++,count++表示的是先赋值,后+1操作;另外一种++count,表示的是先加1操作,之后赋值;
2>先用一个demo来证明一下两种方式的区别;
public class CountTest {
int count = 0;
public int testCount() {
return count++;
}
@Test
public void printCount() {
System.out.println(testCount());
System.out.println(count);
}
}
返回结果为0 1;
public class CountTest {
int count = 0;
public int testCount() {
return ++count;
}
@Test
public void printCount() {
System.out.println(testCount());
System.out.println(count);
}
}
返回结果为1 1;
说明两种操作都是对count执行了加1的操作,但是count++是先返回了结果,再执行了count+1;
3>上面的demo的执行结果可以这么理解
temp = count; 此时count=0;
count = count+1;此时count=1;
count = temp; 此时count=0;
所以最上面的结果为0;如果改成是++count,那么结果就是10;
4>注意,count++不是原子操作,在多线程下会有线程安全问题
@Test
public void manyCountThread() throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(10);
CountDownLatch countDownLatch = new CountDownLatch(1000) {
@Override
public void await() throws InterruptedException {
super.await();
System.out.println(count);
}
};
for(int i=0;i<1000;i++){
executorService.submit(() -> {
count++;
countDownLatch.countDown();
});
}
countDownLatch.await();
}
结果不一定是1000,有可能是987等其他比1000小的数值;这时候可以使用线程安全的类比如AtomicLong;例子如下
public class CountTest {
int count = 0;
private final AtomicLong atomicLong = new AtomicLong(0);
public int testCount() {
return ++count;
}
@Test
public void printCount() {
System.out.println(testCount());
System.out.println(count);
}
@Test
public void manyCountThread() throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(10);
CountDownLatch countDownLatch = new CountDownLatch(1000) {
@Override
public void await() throws InterruptedException {
super.await();
System.out.println(count);
System.out.println(atomicLong);
}
};
for(int i=0;i<1000;i++){
executorService.submit(() -> {
count++;
atomicLong.incrementAndGet();
countDownLatch.countDown();
});
}
countDownLatch.await();
}
}
当然,也可以使用synchronized给count操作的时候加锁;修改下上面的代码,如下即可
Object obj = new Object();
for(int i=0;i<1000;i++){
executorService.submit(() -> {
synchronized (obj){
count++;
}
atomicLong.incrementAndGet();
countDownLatch.countDown();
});
}