• 多线程条件通行工具——Semaphore


    Semaphore的作用是,限制线程通行的数量,如果线程进入时达到通行数量,便等待其它正在通行的线程释放。

    • acquire()
      获取通行
    • release()
      释放通行
    • availablePermits()
      查看通行剩余次数
    • int drainPermits()
      缩减剩余通行次数为0,并返回缩减量
    • reducePermits(int)
      缩减通行次数为指定次数
    • boolean isFair()
      查看是否公平分配通行
    • boolean hasQueuedThreads()
      查看是否有线程在排队
    • int getQueueLength()
      查看排队的长度
    • Collection<Thread> getQueuedThreads()
      查看排队中的所有线程

    源码:

    /**
     * @since 1.5
     * @author Doug Lea
     */
    public class Semaphore implements java.io.Serializable {
        private static final long serialVersionUID = -3222578661600680210L;
        
        private final Sync sync;
    
        public Semaphore(int permits) {
            // 默认使用非公平锁,设置初始的剩余通行量
            sync = new NonfairSync(permits);
        }
    
        public Semaphore(int permits, boolean fair) {
            // 参数决定使用公平还是非公平锁,设置初始的剩余通行量
            sync = fair ? new FairSync(permits) : new NonfairSync(permits);
        }
    
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = 1192457210091910933L;
    
            Sync(int permits) {
                // 设置初始的剩余通行量
                setState(permits);
            }
    
            final int getPermits() {
                // 获取剩余通行量
                return getState();
            }
    
            final int nonfairTryAcquireShared(int acquires) {
                for (;;) {
                    int available = getState();
                    int remaining = available - acquires;
                    // 设置获取后的剩余通行量
                    // 当剩余量小于0时,则阻塞,否则通行
                    if (remaining < 0 || compareAndSetState(available, remaining))
                        return remaining;
                }
            }
    
            protected final boolean tryReleaseShared(int releases) {
                for (;;) {
                    int current = getState();
                    int next = current + releases;
                    // 不允许释放量是负数
                    if (next < current) // overflow
                        throw new Error("Maximum permit count exceeded");
                    // 设置释放后的剩余通行量,返回释放成功,表示需要通知下一个线程通行
                    if (compareAndSetState(current, next))
                        return true;
                }
            }
    
            final void reducePermits(int reductions) {
                for (;;) {
                    int current = getState();
                    int next = current - reductions;
                    // 不允许缩减值是负数
                    if (next > current) // underflow
                        throw new Error("Permit count underflow");
                    // 设置缩减后的剩余通行量
                    if (compareAndSetState(current, next))
                        return;
                }
            }
    
            final int drainPermits() {
                for (;;) {
                    int current = getState();
                    // 直接把剩余通行量设置为0
                    if (current == 0 || compareAndSetState(current, 0))
                        return current;
                }
            }
        }
    
        static final class NonfairSync extends Sync {
            private static final long serialVersionUID = -2694183684443567898L;
    
            NonfairSync(int permits) {
                super(permits);
            }
    
            protected int tryAcquireShared(int acquires) {
                return nonfairTryAcquireShared(acquires);
            }
        }
    
        static final class FairSync extends Sync {
            private static final long serialVersionUID = 2014338818796000944L;
    
            FairSync(int permits) {
                super(permits);
            }
    
            protected int tryAcquireShared(int acquires) {
                for (;;) {
                    // 如果当前线程不位于队头,则阻塞
                    if (hasQueuedPredecessors())
                        return -1;
                    int available = getState();
                    int remaining = available - acquires;
                    // 设置获取后的剩余通行量
                    // 当剩余量小0时,则阻塞,否则通行
                    if (remaining < 0 || compareAndSetState(available, remaining))
                        return remaining;
                }
            }
        }
    
        public void acquire() throws InterruptedException {
            // 获取一次通行,可中断
            sync.acquireSharedInterruptibly(1);
        }
    
        public void acquireUninterruptibly() {
            // 获取一次通行
            sync.acquireShared(1);
        }
    
        public boolean tryAcquire() {
            // 尝试获取一次通行
            return sync.nonfairTryAcquireShared(1) >= 0;
        }
    
        public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
            // 尝试在指定时间内获取一次通行
            return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
        }
    
        public void acquire(int permits) throws InterruptedException {
            if (permits < 0)
                throw new IllegalArgumentException();
            // 获取指定通行次数,可中断
            sync.acquireSharedInterruptibly(permits);
        }
    
        public void acquireUninterruptibly(int permits) {
            if (permits < 0)
                throw new IllegalArgumentException();
            // 获取指定通行次数
            sync.acquireShared(permits);
        }
    
        public boolean tryAcquire(int permits) {
            if (permits < 0)
                throw new IllegalArgumentException();
            // 尝试获取指定通行次数
            return sync.nonfairTryAcquireShared(permits) >= 0;
        }
    
        public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException {
            if (permits < 0)
                throw new IllegalArgumentException();
            // 尝试在指定时间内获取通行
            return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
        }
    
        public void release() {
            // 释放一次通行
            sync.releaseShared(1);
        }
    
        public void release(int permits) {
            if (permits < 0)
                throw new IllegalArgumentException();
            // 释放指定的通行次数
            sync.releaseShared(permits);
        }
    
        public int availablePermits() {
            // 返回剩余的通行量
            return sync.getPermits();
        }
    
        public int drainPermits() {
            // 直接把通行量设置为0
            return sync.drainPermits();
        }
    
        protected void reducePermits(int reduction) {
            if (reduction < 0)
                throw new IllegalArgumentException();
            // 缩减通行量
            sync.reducePermits(reduction);
        }
    
        public boolean isFair() {
            // 返回是否公平锁(即是否公平分配通行)
            return sync instanceof FairSync;
        }
    
        public final boolean hasQueuedThreads() {
            // 返回队列中是否有线程
            return sync.hasQueuedThreads();
        }
    
        public final int getQueueLength() {
            // 返回队列的长度
            return sync.getQueueLength();
        }
    
        protected Collection<Thread> getQueuedThreads() {
            // 返回队列中的所有线程
            return sync.getQueuedThreads();
        }
    
        public String toString() {
            return super.toString() + "[Permits = " + sync.getPermits() + "]";
        }
    }
  • 相关阅读:
    2019年年终总结
    [转]网络基本功08-细说TCP滑动窗口
    anaconda启动报错-pythonw.exe
    FRP+WoL实现远程开机+远程桌面
    [转]网络基本功06-链路聚合
    我的效率工具分享
    比海飞丝更柔顺的写作体验
    阿里云加Picgo或MPic搭建最豪横的图床
    markdown从入门到放弃word和PDF
    Pocket+Evernote 打造个人知识库体系
  • 原文地址:https://www.cnblogs.com/hvicen/p/6242142.html
Copyright © 2020-2023  润新知