线程同步:Semaphore、CyclicBarrier、CountDownLatch

一、Semaphore

Semaphore:信号量,用于限制某段代码的并发数。当permits为1,相当于synchronized。

直接上代码:

    /**
     * test Semaphore
     * 信号量,用于限制某段代码的并发数。
     * 当N为1,相当于synchronized
     */
    private void threadTest5() {
        final int permits = 3;
        final Semaphore semaphore = new Semaphore(permits);

        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 5; i++) {
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    try {

                        //获得许可
                        semaphore.acquire();
                        Log.i(TAG, "run: 剩余许可 = " + semaphore.availablePermits());

                        Thread.sleep(2000);

                        //释放许可
                        semaphore.release();


                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

    }

结果如下,前三条几乎同时打印,后两条是2000ms后打印,可见并发数就是permits值

07-15 22:39:44.218 6810-7087/com.hfy.demo00 I/MainActivityhfy: run: 剩余许可 = 2
07-15 22:39:44.220 6810-7088/com.hfy.demo00 I/MainActivityhfy: run: 剩余许可 = 1
07-15 22:39:44.221 6810-7090/com.hfy.demo00 I/MainActivityhfy: run: 剩余许可 = 0
07-15 22:39:46.220 6810-7089/com.hfy.demo00 I/MainActivityhfy: run: 剩余许可 = 0

07-15 22:39:46.222 6810-7091/com.hfy.demo00 I/MainActivityhfy: run: 剩余许可 = 1


二、CyclicBarrier

CyclicBarrier,循环栅栏,n个线程都await了,才会 各自 继续往下走。(计数器可被重置后使用)

    /**
     * 循环栅栏 CyclicBarrier
     * 大家都await了,才各自继续走。
     */
    private void threadTest6() {
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {
            @Override
            public void run() {
                Log.i(TAG, "run: 线程全都cyclicBarrier.await()了, 那大家都可以继续往下走了~");
            }
        });

        ExecutorService executorService = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 4; i++) {
            final int finalI = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
//                        int numberWaiting = cyclicBarrier.getNumberWaiting();
//                        Log.i(TAG, "run: i="+ finalI + ",numberWaiting = "+ numberWaiting);
                        Log.i(TAG, "run: i=" + finalI + ",我睡1s了,cyclicBarrier.await()");
                        cyclicBarrier.await();
                        Log.i(TAG, "run: i=" + finalI + ",继续往下走了~");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }

                }
            });
        }

    }

结果如下,0、1、2都await了(阻塞了),然后各自都可以继续往下走了。

07-15 22:47:19.888 8140-8235/com.hfy.demo00 I/MainActivityhfy: run: i=2,我睡1s了,cyclicBarrier.await()
07-15 22:47:19.888 8140-8233/com.hfy.demo00 I/MainActivityhfy: run: i=0,我睡1s了,cyclicBarrier.await()
07-15 22:47:19.888 8140-8234/com.hfy.demo00 I/MainActivityhfy: run: i=1,我睡1s了,cyclicBarrier.await()
    run: 线程全都cyclicBarrier.await()了, 那大家都可以继续往下走了~
    run: i=1,继续往下走了~
07-15 22:47:19.889 8140-8233/com.hfy.demo00 I/MainActivityhfy: run: i=0,继续往下走了~
07-15 22:47:19.890 8140-8235/com.hfy.demo00 I/MainActivityhfy: run: i=2,继续往下走了~

07-15 22:47:19.891 8140-8236/com.hfy.demo00 I/MainActivityhfy: run: i=3,我睡1s了,cyclicBarrier.await()


三、CountDownLatch

CountDownLatch,闭锁,我(们) 等(await) 你们都countDown了,才往下走。

    /**
     * 闭锁 CountDownLatch
     * 我(们)await你们都countDown了,才往下走
     */
    private void threadTest7() {
        final CountDownLatch latch = new CountDownLatch(3);

        for (int i = 0; i < 5; i++) {

            ExecutorService executorService = Executors.newFixedThreadPool(10);
            final int finalI = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);

                        Log.i(TAG, "run: i=" + finalI + ",countDown了");
                        latch.countDown();

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        try {
            Log.i(TAG, "threadTest7: 主线程开始等待~");
            latch.await();
            Log.i(TAG, "threadTest7: 主线程继续走了~");
        } catch (
                InterruptedException e)
        {
            e.printStackTrace();
        }
        
    }

结果如下:

07-15 22:52:27.064 8684-8684/com.hfy.demo00 I/MainActivityhfy: threadTest7: 主线程开始等待~
07-15 22:52:28.064 8684-8970/com.hfy.demo00 I/MainActivityhfy: run: i=2,countDown了
07-15 22:52:28.064 8684-8969/com.hfy.demo00 I/MainActivityhfy: run: i=1,countDown了
07-15 22:52:28.064 8684-8968/com.hfy.demo00 I/MainActivityhfy: run: i=0,countDown了
07-15 22:52:28.065 8684-8684/com.hfy.demo00 I/MainActivityhfy: threadTest7: 主线程继续走了~
07-15 22:52:28.065 8684-8972/com.hfy.demo00 I/MainActivityhfy: run: i=4,countDown了
07-15 22:52:28.066 8684-8971/com.hfy.demo00 I/MainActivityhfy: run: i=3,countDown了

猜你喜欢

转载自blog.csdn.net/hfy8971613/article/details/81058054