zoukankan      html  css  js  c++  java
  • Java并发--CountDownLatch CyclicBarrier ReentrantLock

    CountDownLatch

    CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。CountDownLatch使用一个数字count初始化,使用countDown方法使count递减,当count大于0时await方法将一直阻塞,当countDown为0时await方法将立即返回。CountDownLatch有两种典型用法,一是阻塞主线程直到所有子线程执行到某步。二是阻塞子线程直到某条件达成,下面分别是例子。

    public class CountDownLatchTest {
        public static void main(String[] args) throws Exception {
            final CountDownLatch latch = new CountDownLatch(5);
            for (int k = 0; k < 5; k++) {
                final int n = k;
                new Thread(new Runnable() {
                    private int id = n;
                    @Override
                    public void run() {
                        try {
                            System.out.println("thread " + id + " begin.");
                            TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException e) {
                        }
                        System.out.println("thread " + id + " run over.");
                        latch.countDown();
                    }
                }).start();
            }
            latch.await();
            System.out.println("main end");
        }
    }

    ---

    public class CountDownLatchTest {
        public static void main(String[] args) throws Exception {
            final CountDownLatch latch = new CountDownLatch(1);
            for (int k = 0; k < 5; k++) {
                final int n = k;
                new Thread(new Runnable() {
                    private int id = n;
                    @Override
                    public void run() {
                        try {
                            System.out.println("thread " + id + " begin.");
                            latch.await();
                        } catch (InterruptedException e) {
                        }
                        System.out.println("thread " + id + " run over.");
                        latch.countDown();
                    }
                }).start();
            }
            latch.countDown();
            System.out.println("main end");
        }
    }

    ---

    CyclicBarrier

    CyclicBarrier在初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。

    CyclicBarrier初始时还可带一个Runnable的参数, 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。通过reset函数可重置该锁。

    public class CyclicBarrierTest {
    
        public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
            CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
                @Override
                public void run() {
                    //当所有线程到达barrier时执行
                    System.out.println("Barrier action");
                }
            });
    
            for (int k = 0; k < 4; k++) {
                final int n = k;
                new Thread(new Runnable() {
                    private int id = n;
                    @Override
                    public void run() {
                        try {
                            System.out.println("thread " + id + " begin.");
                            TimeUnit.SECONDS.sleep(1);
                            //线程在这里等待,直到所有线程都到达barrier
                            barrier.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } catch (BrokenBarrierException e) {
                            e.printStackTrace();
                        }
                        System.out.println("thread " + id + " run over.");
                    }
                }).start();
            }
    
            System.out.println("main end");
        }
    }

    ---

    ReentrantLock

    ReentrantLock是Java concurrent包中的一个互斥锁,它可以用来替代synchronized关键字,使用更加灵活。该锁同一时间只能被一个线程拥有,即执行了lock()但还未执行unlock()的线程。

    /*
     * ReentrantLock用来对一段代码上锁,可以代替synchronized关键字。
     */
    class SomeClassWithLock {
    
        private long count1 = 0;
        private long count2 = 0;
        
        //A ReentrantLock is owned by the thread last successfully locking, but not yet unlocking it.
        private ReentrantLock lock = new ReentrantLock();
    
        public void test() {
    
            //++并非原子操作,此处未上锁
            count1++;
    
            lock.lock();
            try {
                //此处线程安全
                count2++;
            } finally {
                //将unlock放在finally块里面
                lock.unlock();
            }
        }
    
        public long get1() {
            return count1;
        }
        public long get2() {
            return count2;
        }
    }
    
    public class ReentrantLockTest {
    
        public static void main(String[] args) {
    
            final int COUNT = 10;
            final CountDownLatch startSignal = new CountDownLatch(1);
            final CountDownLatch doneSignal = new CountDownLatch(COUNT);
    
            final SomeClassWithLock someClass = new SomeClassWithLock();
    
            for (int i = 0; i < COUNT; ++i) {
                final int index = i;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            startSignal.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        for (int j = 0; j < 1000; ++j) {
                            someClass.test();
                        }
                        System.out.println("running thread " + index);
                        doneSignal.countDown();
                    }
                }).start();
            }
    
            startSignal.countDown();
            try {
                doneSignal.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println("count1:" + someClass.get1());
            System.out.println("count2:" + someClass.get2());
        }
    
    }

    ---

    执行结果:

    running thread 4
    running thread 7
    running thread 8
    running thread 2
    running thread 6
    running thread 0
    running thread 5
    running thread 9
    running thread 1
    running thread 3
    count1:9988
    count2:10000

    end

  • 相关阅读:
    洛谷P1421 小玉买文具
    洛谷P1035 级数求和
    洛谷 P2337 【[SCOI2012]喵星人的入侵】
    洛谷P1002 过河卒
    洛谷 P4073 [WC2013]平面图
    洛谷 P4705 玩游戏
    python3.7-初学篇-06
    python3.7-初学篇-04
    python3.7-初学篇-03
    python3.7-初学篇-02
  • 原文地址:https://www.cnblogs.com/luangeng/p/6568476.html
Copyright © 2011-2022 走看看