Java并发Semaphore

Semaphore限制一个可以同时访问共享资源的总数,好比多个线程获取一定数据的许可证,获取到了许可证的都可以执行。最典型的例子就是数据库连接池的应用。

构造器:

Semaphore(int permits)Creates a Semaphore with the given number of permits and nonfair fairness setting.
Semaphore(int permits, boolean fair)Creates a Semaphore with the given number of permits and the given fairness setting.

方法:

voidacquire()Acquires a permit from this semaphore, blocking until one is available, or the thread is interrupted.
voidacquire(int permits)Acquires the given number of permits from this semaphore, blocking until all are available, or the thread is interrupted.
voidacquireUninterruptibly()Acquires a permit from this semaphore, blocking until one is available.
voidacquireUninterruptibly(int permits)Acquires the given number of permits from this semaphore, blocking until all are available.
intavailablePermits()Returns the current number of permits available in this semaphore.
intdrainPermits()Acquires and returns all permits that are immediately available.
protected Collection<Thread>getQueuedThreads()Returns a collection containing threads that may be waiting to acquire.
intgetQueueLength()Returns an estimate of the number of threads waiting to acquire.
booleanhasQueuedThreads()Queries whether any threads are waiting to acquire.
booleanisFair()Returns true if this semaphore has fairness set true.
protected voidreducePermits(int reduction)Shrinks the number of available permits by the indicated reduction.
voidrelease()Releases a permit, returning it to the semaphore.
voidrelease(int permits)Releases the given number of permits, returning them to the semaphore.
StringtoString()Returns a string identifying this semaphore, as well as its state.
booleantryAcquire()Acquires a permit from this semaphore, only if one is available at the time of invocation.
booleantryAcquire(int permits)Acquires the given number of permits from this semaphore, only if all are available at the time of invocation.
booleantryAcquire(int permits, long timeout, TimeUnit unit)Acquires the given number of permits from this semaphore, if all become available within the given waiting time and the current thread has not been interrupted.
booleantryAcquire(long timeout, TimeUnit unit)Acquires a permit from this semaphore, if one becomes available within the given waiting time and the current thread has not been interrupted.

demo代码:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {

    private final Set<String> sets;
    private final Semaphore semaphore;

    public SemaphoreTest(int n) {
        sets = new HashSet<>();
        this.semaphore = new Semaphore(n);
    }

    public static void main(String[] args) throws InterruptedException {
        SemaphoreTest st = new SemaphoreTest(10);
        List<Thread> ts = new ArrayList<>();
        for(int i=0; i<15; i++) {
            Thread t = new Thread(()->{
                int j=0;
                while(j<3) {
                    try {
                        st.semaphore.acquire();
                        st.sets.add(Thread.currentThread().getName());
                        System.out.println(Thread.currentThread().getName()+" add set ing ...");
                        j++;
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        st.semaphore.release();
                    }
                }
            });
            ts.add(t);
        }
        for(Thread t: ts) {
            t.start();
        }
        Thread.sleep(10000);
        st.sets.forEach(System.out::println);
    }
}

输出:

Thread-0 add set ing ...
Thread-4 add set ing ...
Thread-3 add set ing ...
Thread-7 add set ing ...
Thread-8 add set ing ...
Thread-11 add set ing ...
Thread-12 add set ing ...
Thread-2 add set ing ...
Thread-6 add set ing ...
Thread-10 add set ing ...
Thread-0 add set ing ...
Thread-4 add set ing ...
Thread-3 add set ing ...
Thread-11 add set ing ...
Thread-7 add set ing ...
Thread-14 add set ing ...
Thread-12 add set ing ...
Thread-1 add set ing ...
Thread-10 add set ing ...
Thread-6 add set ing ...
Thread-0 add set ing ...
Thread-4 add set ing ...
Thread-3 add set ing ...
Thread-7 add set ing ...
Thread-14 add set ing ...
Thread-11 add set ing ...
Thread-12 add set ing ...
Thread-6 add set ing ...
Thread-10 add set ing ...
Thread-5 add set ing ...
Thread-9 add set ing ...
Thread-13 add set ing ...
Thread-8 add set ing ...
Thread-14 add set ing ...
Thread-2 add set ing ...
Thread-1 add set ing ...
Thread-5 add set ing ...
Thread-9 add set ing ...
Thread-13 add set ing ...
Thread-8 add set ing ...
Thread-2 add set ing ...
Thread-1 add set ing ...
Thread-5 add set ing ...
Thread-9 add set ing ...
Thread-13 add set ing ...
Thread-3
Thread-4
Thread-5
Thread-6
Thread-7
Thread-8
Thread-9
Thread-11
Thread-10
Thread-14
Thread-13
Thread-12
Thread-0
Thread-1
Thread-2

运行代码可以看出,实际运行时,基本上是10个打印一起输出的,因为信号量设置的是10,所以同时能够执行的只有10个线程。