并发编程

61 阅读1分钟

前言

10w个用户,对某个按钮点50次

四种方式

public class ClickDemo {

    public static final int SIZE = 100000;
    public static final int THREAD_NUMBER = 50;


    public static void main(String[] args) throws Exception {

        clickBySynchronized();
        clickByAtomicLong();
        clickByLongAdder();
        clickByLongAccumulator();

    }


    public static void clickBySynchronized() throws Exception {
        ClickNumber clickNumber = new ClickNumber();
        CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUMBER);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_NUMBER; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < SIZE; j++) {
                        clickNumber.clickBySynchronized();
                    }
                } finally {
                    countDownLatch.countDown();
                }
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        long endTime = System.currentTimeMillis();
        System.out.println("clickBySynchronized cost:" + (endTime - startTime) + "ms" + "\t" + clickNumber.number);
    }

    public static void clickByAtomicLong() throws Exception {
        ClickNumber clickNumber = new ClickNumber();
        CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUMBER);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_NUMBER; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < SIZE; j++) {
                        clickNumber.clickByAtomicLong();
                    }
                } finally {
                    countDownLatch.countDown();
                }
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        long endTime = System.currentTimeMillis();
        System.out.println("clickByAtomicLong cost:" + (endTime - startTime) + "ms" + "\t" + clickNumber.atomicLong.get());
    }

    public static void clickByLongAdder() throws Exception {
        ClickNumber clickNumber = new ClickNumber();
        CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUMBER);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_NUMBER; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < SIZE; j++) {
                        clickNumber.clickByLongAdder();
                    }
                } finally {
                    countDownLatch.countDown();
                }
            }, String.valueOf(i)).start();
        }

        countDownLatch.await();

        long endTime = System.currentTimeMillis();
        System.out.println("clickByLongAdder cost:" + (endTime - startTime) + "ms" + "\t" + clickNumber.longAdder.sum());
    }

    public static void clickByLongAccumulator() throws Exception {
        ClickNumber clickNumber = new ClickNumber();
        CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUMBER);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_NUMBER; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < SIZE; j++) {
                        clickNumber.clickByLongAccumulator();
                    }
                } finally {
                    countDownLatch.countDown();
                }
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        long endTime = System.currentTimeMillis();
        System.out.println("clickByLongAccumulator cost:" + (endTime - startTime) + "ms" + "\t" + clickNumber.longAccumulator.get());
    }


}

class ClickNumber {

    int number = 0;

    public synchronized void clickBySynchronized() {
        number++;
    }

    AtomicLong atomicLong = new AtomicLong(0);

    public void clickByAtomicLong() {
        atomicLong.getAndIncrement();
    }

    LongAdder longAdder = new LongAdder();

    public void clickByLongAdder() {
        longAdder.increment();
    }

    LongAccumulator longAccumulator = new LongAccumulator((x, y) -> x + y, 0);

    public void clickByLongAccumulator() {
        longAccumulator.accumulate(1);
    }


}

image.png

可以看出,高并发的情况下,LongAdder 的性能比 AtomicLong 高很多