用程序员的语言: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();
    }
}
发布了85 篇原创文章 · 获赞 21 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_41670928/article/details/103063523
今日推荐