• coutdownlatch的使用


    package com.example.demo;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Random;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 关于计数器(countdownlathch)的使用
     * 当计数器为0时,唤醒使用计数器锁住的线程,注意一个线程可能会执行俩次,可能需要sychronized去控制
     */
    public class CountdownTest {
    
    
        public static void main(String[] args) {
            CountDownLatch countDownLatch = new CountDownLatch(3);
            // 构造一个线程池
            ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),
                    new ThreadPoolExecutor.DiscardOldestPolicy());
    
            Thread t1 = new Thread(new Customer(countDownLatch, "t1"));
    
            Thread t2 = new Thread(new Customer(countDownLatch, "t2"));
    
            Thread t3 = new Thread(new Customer(countDownLatch, "t3"));
    
            Thread t4 = new Thread(new Waitress(countDownLatch, "t4"));
            threadPool.execute(t1);
            threadPool.execute(t2);
            threadPool.execute(t3);
            threadPool.execute(t4);
        }
    
    
    }
    
    class Customer implements Runnable {
        private CountDownLatch latch;
        private String name;
    
        public Customer(CountDownLatch latch, String name) {
            this.latch = latch;
            this.name = name;
        }
    
        @Override
        public void run() {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
                Random random = new Random();
    
                System.out.println(sdf.format(new Date()) + " " + name + "出发去饭店");
                Thread.sleep((long) (random.nextDouble() * 3000) + 1000);
                System.out.println(sdf.format(new Date()) + " " + name + "到了饭店");
                latch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    class Waitress implements Runnable {
        private CountDownLatch latch;
        private String name;
    
        public Waitress(CountDownLatch latch, String name) {
            this.latch = latch;
            this.name = name;
        }
    
        @Override
        public void run() {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
                System.out.println(sdf.format(new Date()) + " " + name + "等待顾客");
                latch.await();
                System.out.println(sdf.format(new Date()) + " " + name + "开始上菜");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    latch.countDown();
    //=====================
     public void countDown() {
            sync.releaseShared(1);
        }
    //=====================
      public final boolean releaseShared(int arg) {
            if (tryReleaseShared(arg)) {
                doReleaseShared();
                return true;
            }
            return false;
        }
    //=====================
    private void doReleaseShared() {
            /*
             * Ensure that a release propagates, even if there are other
             * in-progress acquires/releases.  This proceeds in the usual
             * way of trying to unparkSuccessor of head if it needs
             * signal. But if it does not, status is set to PROPAGATE to
             * ensure that upon release, propagation continues.
             * Additionally, we must loop in case a new node is added
             * while we are doing this. Also, unlike other uses of
             * unparkSuccessor, we need to know if CAS to reset status
             * fails, if so rechecking.
             */
            for (;;) {
                Node h = head;
                if (h != null && h != tail) {
                    int ws = h.waitStatus;
                    if (ws == Node.SIGNAL) {
                        if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                            continue;            // loop to recheck cases
                        unparkSuccessor(h);
                    }
                    else if (ws == 0 &&
                             !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                        continue;                // loop on failed CAS
                }
                if (h == head)                   // loop if head changed
                    break;
            }
        }
     latch.await();
    //=======================
        public void await() throws InterruptedException {
            sync.acquireSharedInterruptibly(1);
        }
    //=======================
        public final void acquireSharedInterruptibly(int arg)
                throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            if (tryAcquireShared(arg) < 0)
                doAcquireSharedInterruptibly(arg);
        }
    //=======================
    private void doAcquireSharedInterruptibly(int arg)
            throws InterruptedException {
            final Node node = addWaiter(Node.SHARED);
            boolean failed = true;
            try {
                for (;;) {
                    final Node p = node.predecessor();
                    if (p == head) {
                        int r = tryAcquireShared(arg);
                        if (r >= 0) {
                            setHeadAndPropagate(node, r);
                            p.next = null; // help GC
                            failed = false;
                            return;
                        }
                    }
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                        throw new InterruptedException();
                }
            } finally {
                if (failed)
                    cancelAcquire(node);
            }
        }
  • 相关阅读:
    基于vue2.0 +vuex+ element-ui后台管理系统:包括本地开发调试详细步骤
    require.js实现js模块化编程(二):RequireJS Optimizer
    require.js实现js模块化编程(一)
    树型权限管理插件:jQuery Tree Multiselect详细使用指南
    表格组件神器:bootstrap table详细使用指南
    后台管理系统中的重点知识大全
    Ajax最详细的参数解析和场景应用
    npm常用命令小结
    详解javascript,ES5标准中新增的几种高效Object操作方法
    git入门学习(二):新建分支/上传代码/删除分支
  • 原文地址:https://www.cnblogs.com/xiaoshahai/p/12895874.html
Copyright © 2020-2023  润新知