用程序员的语言:5000工科男抢200女同学做女朋友,怎么完美解决

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();
    }
}

 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值