1、有人在群里喊为啥我的打印结果不对,我一看写的还挺有意思,不仅用到了
Semaphore,还有线程管控和排序问题。就帮着改了一下。
原来的代码是这样写的:
public class JiShuDemo {
/**
* @Description: 当只有一个线程去执行加一的操作时,最终的结果都是等于总数5000
* 但是,若是两个及以上的线程 同时执行加一操作,那么最终的结果只能是 小于5000
* 关于线程并发的 一个计数 demo
* @Author ljc
* @Date 2019/11/14 9:43
**/
//线程总数
private static int threadTotal = 200;
//总数
private static int clientTotal = 5000;
private static volatile AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
for (int i=0;i<clientTotal;i++) {
exec.execute(()->{
try {
semaphore.acquire();
add();
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
exec.shutdown();
System.out.println("最后的总数:"+count);
}
private synchronized static void add(){
count.incrementAndGet();
}
}
add()方法加了synchronized这样的重锁,并发效率一定很低,所以我首先给他换成了AtomicInteger。
再看,打印结果一直比5000小,是因为线程池里的线程没有执行完毕,main线程就把权限抢过来了。这是典型的“秦灭六国,一统华夏”的问题。要先保证六国被灭,才能一统天下。
所以我用了CountDownLatch来保证线程执行的次序,即main线程最后一个被执行。
2、修改后的代码如下:
/**
* @program: mybatis
* @description: 其他人的问题
* @author: Miller.FAN
* @create: 2019-11-14 10:34
**/
public class JiShuDemo {
/**
* @Description: 5000个人抢200个手机,最后还要正确显示出,每个人确实抢了一次,统计抢的次数是5000,怎么实现?
* @Author ljc
* @Date 2019/11/14 9:43
**/
//线程总数
private static int threadTotal = 200;
//总数
private static int clientTotal = 5000;
private static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(5000);
ExecutorService exec = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
for (int i=0;i<clientTotal;i++) {
exec.execute(()->{
try {
semaphore.acquire();
add();
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
});
}
exec.shutdown();
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("最后的总数:"+count);
}
private static void add(){
count.incrementAndGet();
}
}