Java : Semaphore with Examples

Semaphore (Java SE 19 & JDK 19) API Examples.
You will find code examples on most Semaphore methods.


Summary

A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer.

Class diagram

final var semaphore = new Semaphore(3);
System.out.println("permits = " + semaphore.availablePermits());

System.out.println("-- start --");
try (final var executor = Executors.newFixedThreadPool(5)) {
    for (int i = 1; i <= 5; i++) {
        final var id = i;
        TimeUnit.MILLISECONDS.sleep(100);

        executor.submit(() -> {
            try {
                System.out.println(id + " : try acquire ...");
                semaphore.acquire();
                try {
                    System.out.println(id + " : OK! : permits = " + semaphore.availablePermits());

                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(id + " : sleep completed (release!)");
                } finally {
                    semaphore.release();
                }
            } catch (InterruptedException e) {
                System.out.println("InterruptedException!");
            }
        });
    }
}

System.out.println("-- end --");
System.out.println("permits = " + semaphore.availablePermits());

// Result
// ↓
//permits = 3
//-- start --
//1 : try acquire ...
//1 : OK! : permits = 2
//2 : try acquire ...
//2 : OK! : permits = 1
//3 : try acquire ...
//3 : OK! : permits = 0
//4 : try acquire ...
//5 : try acquire ...
//1 : sleep completed (release!)
//4 : OK! : permits = 0
//2 : sleep completed (release!)
//5 : OK! : permits = 0
//3 : sleep completed (release!)
//4 : sleep completed (release!)
//5 : sleep completed (release!)
//-- end --
//permits = 3

Constructors

Semaphore (int permits)

Creates a Semaphore with the given number of permits and nonfair fairness setting.

Please see acquire().

Semaphore (int permits, boolean fair)

Creates a Semaphore with the given number of permits and the given fairness setting.

Please see acquire() for permits parameter.

void testFair(boolean fair) throws InterruptedException {
    final var semaphore = new Semaphore(5, fair);
    System.out.println("isFair = " + semaphore.isFair());
    System.out.println("permits = " + semaphore.availablePermits());

    try (final var executor = Executors.newFixedThreadPool(3)) {
        class Task implements Runnable {
            private final String name;
            private final int numOfPermits;

            Task(String name, int numOfPermits) {
                this.name = name;
                this.numOfPermits = numOfPermits;
            }

            @Override
            public void run() {
                System.out.printf("%s : try acquire ... (%d)%n", name, numOfPermits);
                semaphore.acquireUninterruptibly(numOfPermits);
                try {
                    System.out.printf("%s : OK! (%d)%n", name, numOfPermits);

                    TimeUnit.SECONDS.sleep(1);
                    System.out.printf("%s : release! (%d)%n", name, numOfPermits);
                } catch (InterruptedException e) {
                    System.out.println("InterruptedException!");
                } finally {
                    semaphore.release(numOfPermits);
                }
            }
        }

        executor.submit(new Task("A", 4));
        TimeUnit.MILLISECONDS.sleep(100);

        executor.submit(new Task("B", 5));
        TimeUnit.MILLISECONDS.sleep(100);

        executor.submit(new Task("C", 1));
    }

    System.out.println("permits = " + semaphore.availablePermits());
}
testFair(true);

// Result
// ↓
//isFair = true
//permits = 5
//A : try acquire ... (4)
//A : OK! (4)
//B : try acquire ... (5)
//C : try acquire ... (1)
//A : release! (4)
//B : OK! (5)
//B : release! (5)
//C : OK! (1)
//C : release! (1)
//permits = 5

testFair(false);

// Result
// ↓
//isFair = false
//permits = 5
//A : try acquire ... (4)
//A : OK! (4)
//B : try acquire ... (5)
//C : try acquire ... (1)
//C : OK! (1)
//A : release! (4)
//C : release! (1)
//B : OK! (5)
//B : release! (5)
//permits = 5

Methods

void acquire ()

Acquires a permit from this semaphore, blocking until one is available, or the thread is interrupted.

final var semaphore = new Semaphore(3);
System.out.println("permits = " + semaphore.availablePermits());

System.out.println("-- start --");
try (final var executor = Executors.newFixedThreadPool(5)) {
    for (int i = 1; i <= 5; i++) {
        final var id = i;
        TimeUnit.MILLISECONDS.sleep(100);

        executor.submit(() -> {
            try {
                System.out.println(id + " : try acquire ...");
                semaphore.acquire();
                try {
                    System.out.println(id + " : OK! : permits = " + semaphore.availablePermits());

                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(id + " : sleep completed (release!)");
                } finally {
                    semaphore.release();
                }
            } catch (InterruptedException e) {
                System.out.println("InterruptedException!");
            }
        });
    }
}

System.out.println("-- end --");
System.out.println("permits = " + semaphore.availablePermits());

// Result
// ↓
//permits = 3
//-- start --
//1 : try acquire ...
//1 : OK! : permits = 2
//2 : try acquire ...
//2 : OK! : permits = 1
//3 : try acquire ...
//3 : OK! : permits = 0
//4 : try acquire ...
//5 : try acquire ...
//1 : sleep completed (release!)
//4 : OK! : permits = 0
//2 : sleep completed (release!)
//5 : OK! : permits = 0
//3 : sleep completed (release!)
//4 : sleep completed (release!)
//5 : sleep completed (release!)
//-- end --
//permits = 3

void acquire (int permits)

Acquires the given number of permits from this semaphore, blocking until all are available, or the thread is interrupted.

final var semaphore = new Semaphore(7);
try (final var executor = Executors.newFixedThreadPool(5)) {
    for (int i = 1; i <= 5; i++) {
        final var id = i;
        TimeUnit.MILLISECONDS.sleep(100);

        executor.submit(() -> {
            try {
                System.out.println(id + " : try acquire ... : permits = "
                        + semaphore.availablePermits());
                semaphore.acquire(2);
                try {
                    System.out.println(id + " : OK! : permits = "
                            + semaphore.availablePermits());

                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(id + " : sleep completed (release!)");
                } finally {
                    semaphore.release(2);
                }
            } catch (InterruptedException e) {
                System.out.println("InterruptedException!");
            }
        });
    }
}

System.out.println("-- all tasks end --");
System.out.println("available : " + semaphore.availablePermits());

// Result
// ↓
//1 : try acquire ... : permits = 7
//1 : OK! : permits = 5
//2 : try acquire ... : permits = 5
//2 : OK! : permits = 3
//3 : try acquire ... : permits = 3
//3 : OK! : permits = 1
//4 : try acquire ... : permits = 1
//5 : try acquire ... : permits = 1
//1 : sleep completed (release!)
//4 : OK! : permits = 1
//2 : sleep completed (release!)
//5 : OK! : permits = 1
//3 : sleep completed (release!)
//4 : sleep completed (release!)
//5 : sleep completed (release!)
//-- all tasks end --
//available : 7

void acquireUninterruptibly ()

Acquires a permit from this semaphore, blocking until one is available.

Please see also : acquire()

final var semaphore = new Semaphore(0);

try (final var executor = Executors.newSingleThreadExecutor()) {
    try {
        final var future = executor.submit(() -> {
            System.out.println("try acquire ... : permits = " + semaphore.availablePermits());
            semaphore.acquireUninterruptibly();
            System.out.println("acquire OK!");
            System.out.println("isInterrupted : " + Thread.currentThread().isInterrupted());
        });

        TimeUnit.SECONDS.sleep(1);

        final var ret = future.cancel(true);
        System.out.println("cancel = " + ret);
        System.out.println("release!");
    } finally {
        semaphore.release();
    }
}

System.out.println("------");
System.out.println("permits = " + semaphore.availablePermits());

// Result
// ↓
//try acquire ... : permits = 0
//cancel = true
//release!
//acquire OK!
//isInterrupted : true
//------
//permits = 0
final var semaphore = new Semaphore(0);

try (final var executor = Executors.newSingleThreadExecutor()) {
    final var future = executor.submit(() -> {
        try {
            System.out.println("try acquire ... : permits = " + semaphore.availablePermits());
            semaphore.acquire();
            System.out.println("acquire OK!");
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        }
    });

    TimeUnit.SECONDS.sleep(1);

    final var ret = future.cancel(true);
    System.out.println("cancel = " + ret);
}

System.out.println("------");
System.out.println("permits = " + semaphore.availablePermits());

// Result
// ↓
//try acquire ... : permits = 0
//InterruptedException!
//cancel = true
//------
//permits = 0

void acquireUninterruptibly (int permits)

Acquires the given number of permits from this semaphore, blocking until all are available.

Please see also : acquire(int permits)

final var semaphore = new Semaphore(0);

try (final var executor = Executors.newSingleThreadExecutor()) {
    try {
        final var future = executor.submit(() -> {
            System.out.println("try acquire ... : permits = " + semaphore.availablePermits());
            semaphore.acquireUninterruptibly(2);
            System.out.println("acquire OK!");
            System.out.println("isInterrupted : " + Thread.currentThread().isInterrupted());
        });

        TimeUnit.SECONDS.sleep(1);

        final var ret = future.cancel(true);
        System.out.println("cancel = " + ret);
        System.out.println("release!");
    } finally {
        semaphore.release(2);
    }
}

System.out.println("------");
System.out.println("permits = " + semaphore.availablePermits());

// Result
// ↓
//try acquire ... : permits = 0
//cancel = true
//release!
//acquire OK!
//isInterrupted : true
//------
//permits = 0
final var semaphore = new Semaphore(0);

try (final var executor = Executors.newSingleThreadExecutor()) {
    final var future = executor.submit(() -> {
        try {
            System.out.println("try acquire ... : permits = " + semaphore.availablePermits());
            semaphore.acquire(2);
            System.out.println("acquire OK!");
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        }
    });

    TimeUnit.SECONDS.sleep(1);

    final var ret = future.cancel(true);
    System.out.println("cancel = " + ret);
}

System.out.println("------");
System.out.println("permits = " + semaphore.availablePermits());

// Result
// ↓
//try acquire ... : permits = 0
//InterruptedException!
//cancel = true
//------
//permits = 0

int availablePermits ()

Returns the current number of permits available in this semaphore.

Please see acquire().

int drainPermits ()

Acquires and returns all permits that are immediately available, or if negative permits are available, releases them.

final var semaphore = new Semaphore(5);
System.out.println(semaphore.availablePermits()); // 5

final var ret = semaphore.drainPermits();
System.out.println(ret); // 5

System.out.println(semaphore.availablePermits()); // 0
final var semaphore = new Semaphore(-3);
System.out.println(semaphore.availablePermits()); // -3

final var ret = semaphore.drainPermits();
System.out.println(ret); // -3

System.out.println(semaphore.availablePermits()); // 0

protected Collection<Thread> getQueuedThreads ()

Returns a collection containing threads that may be waiting to acquire.

protected. I think it's rare to create a subclass of this class. Therefore, the code example is omitted.

final int getQueueLength ()

Returns an estimate of the number of threads waiting to acquire.

final var semaphore = new Semaphore(2);

try (final var executor = Executors.newFixedThreadPool(6)) {
    for (int i = 1; i <= 6; i++) {
        final var id = i;
        TimeUnit.MILLISECONDS.sleep(100);

        executor.submit(() -> {
            try {
                System.out.printf("%d : try acquire ... : queue length = %d (%b)%n",
                        id, semaphore.getQueueLength(), semaphore.hasQueuedThreads());
                semaphore.acquire();
                try {
                    System.out.printf("%d : OK! : queue length = %d%n",
                            id, semaphore.getQueueLength());

                    TimeUnit.SECONDS.sleep(3);
                    System.out.printf("%d : sleep completed (release!)%n", id);
                } finally {
                    semaphore.release();
                }
            } catch (InterruptedException e) {
                System.out.println("InterruptedException!");
            }
        });
    }
}

// Result
// ↓
//1 : try acquire ... : queue length = 0 (false)
//1 : OK! : queue length = 0
//2 : try acquire ... : queue length = 0 (false)
//2 : OK! : queue length = 0
//3 : try acquire ... : queue length = 0 (false)
//4 : try acquire ... : queue length = 1 (true)
//5 : try acquire ... : queue length = 2 (true)
//6 : try acquire ... : queue length = 3 (true)
//1 : sleep completed (release!)
//3 : OK! : queue length = 3
//2 : sleep completed (release!)
//4 : OK! : queue length = 2
//3 : sleep completed (release!)
//5 : OK! : queue length = 1
//4 : sleep completed (release!)
//6 : OK! : queue length = 0
//5 : sleep completed (release!)
//6 : sleep completed (release!)

final boolean hasQueuedThreads ()

Queries whether any threads are waiting to acquire.

Please see getQueueLength().

boolean isFair ()

Returns true if this semaphore has fairness set true.

Please see Semaphore(int permits, boolean fair).

protected void reducePermits (int reduction)

Shrinks the number of available permits by the indicated reduction.

protected. I think it's rare to create a subclass of this class. Therefore, the code example is omitted.

void release ()

Releases a permit, returning it to the semaphore.

Please see acquire().

void release (int permits)

Releases the given number of permits, returning them to the semaphore.

Please see acquire(int permits).

String toString ()

Returns a string identifying this semaphore, as well as its state.

final var semaphore = new Semaphore(5);

final var str1 = semaphore.toString();
System.out.println(str1); // java.util.concurrent.Semaphore@503f91c3[Permits = 5]

semaphore.drainPermits();

final var str2 = semaphore.toString();
System.out.println(str2); // java.util.concurrent.Semaphore@503f91c3[Permits = 0]

boolean tryAcquire ()

Acquires a permit from this semaphore, only if one is available at the time of invocation.

final var semaphore = new Semaphore(3);
try (final var executor = Executors.newFixedThreadPool(5)) {
    for (int i = 1; i <= 5; i++) {
        final var id = i;
        TimeUnit.MILLISECONDS.sleep(100);

        executor.submit(() -> {
            if (semaphore.tryAcquire()) {
                try {
                    System.out.printf("%d : try acquire = true : permits = %d%n",
                            id, semaphore.availablePermits());

                    TimeUnit.SECONDS.sleep(3);
                    System.out.printf("%d : sleep completed (release!)%n", id);
                } catch (InterruptedException e) {
                    System.out.println("InterruptedException!");
                } finally {
                    semaphore.release();
                }
            } else {
                System.out.printf("%d : try acquire = false : permits = %d%n",
                        id, semaphore.availablePermits());
            }
        });
    }
}

System.out.println("-- all tasks end --");
System.out.println("permits : " + semaphore.availablePermits());

// Result
// ↓
//1 : try acquire = true : permits = 2
//2 : try acquire = true : permits = 1
//3 : try acquire = true : permits = 0
//4 : try acquire = false : permits = 0
//5 : try acquire = false : permits = 0
//1 : sleep completed (release!)
//2 : sleep completed (release!)
//3 : sleep completed (release!)
//-- all tasks end --
//permits : 3

boolean tryAcquire (int permits)

Acquires the given number of permits from this semaphore, only if all are available at the time of invocation.

final var semaphore = new Semaphore(6);
try (final var executor = Executors.newFixedThreadPool(5)) {
    for (int i = 1; i <= 5; i++) {
        final var id = i;
        TimeUnit.MILLISECONDS.sleep(100);

        executor.submit(() -> {
            if (semaphore.tryAcquire(2)) {
                try {
                    System.out.printf("%d : try acquire = true : permits = %d%n",
                            id, semaphore.availablePermits());

                    TimeUnit.SECONDS.sleep(3);
                    System.out.printf("%d : sleep completed (release!)%n", id);
                } catch (InterruptedException e) {
                    System.out.println("InterruptedException!");
                } finally {
                    semaphore.release(2);
                }
            } else {
                System.out.printf("%d : try acquire = false : permits = %d%n",
                        id, semaphore.availablePermits());
            }
        });
    }
}

System.out.println("-- all tasks end --");
System.out.println("permits : " + semaphore.availablePermits());

// Result
// ↓
//1 : try acquire = true : permits = 4
//2 : try acquire = true : permits = 2
//3 : try acquire = true : permits = 0
//4 : try acquire = false : permits = 0
//5 : try acquire = false : permits = 0
//1 : sleep completed (release!)
//2 : sleep completed (release!)
//3 : sleep completed (release!)
//-- all tasks end --
//permits : 6

boolean tryAcquire (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.

Please see also : tryAcquire(int permits)

final var current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

final var semaphore = new Semaphore(2);
try (final var executor = Executors.newFixedThreadPool(3)) {

    class Task implements Runnable {
        private final String id;
        private final long timeout;

        Task(String id, long timeout) {
            this.id = id;
            this.timeout = timeout;
        }

        @Override
        public void run() {
            System.out.printf("%s : start : timeout = %d sec. : permits = %d%n",
                    id, timeout, semaphore.availablePermits());
            try {
                if (semaphore.tryAcquire(2, timeout, TimeUnit.SECONDS)) {
                    try {
                        System.out.printf("%s : try acquire = true (%f sec.)%n",
                                id, elapsedTime.getAsDouble());

                        TimeUnit.SECONDS.sleep(3);
                        System.out.printf("%s : sleep completed : release! (%f sec.)%n",
                                id, elapsedTime.getAsDouble());
                    } finally {
                        semaphore.release(2);
                    }
                } else {
                    System.out.printf("%s : try acquire = false : Timeout! (%f sec.)%n",
                            id, elapsedTime.getAsDouble());
                }
            } catch (InterruptedException e) {
                System.out.println("InterruptedException!");
            }
        }
    }

    executor.submit(new Task("A", 1));
    TimeUnit.MILLISECONDS.sleep(100);

    executor.submit(new Task("B", 2));
    TimeUnit.MILLISECONDS.sleep(100);

    executor.submit(new Task("C", 5));
}

System.out.println("-- all tasks end --");
System.out.println("permits : " + semaphore.availablePermits());

// Result
// ↓
//A : start : timeout = 1 sec. : permits = 2
//A : try acquire = true (0.003661 sec.)
//B : start : timeout = 2 sec. : permits = 0
//C : start : timeout = 5 sec. : permits = 0
//B : try acquire = false : Timeout! (2.126545 sec.)
//A : sleep completed : release! (3.017536 sec.)
//C : try acquire = true (3.018140 sec.)
//C : sleep completed : release! (6.027912 sec.)
//-- all tasks end --
//permits : 2

boolean tryAcquire (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.

Please see also : tryAcquire()

final var current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

final var semaphore = new Semaphore(1);
try (final var executor = Executors.newFixedThreadPool(3)) {

    class Task implements Runnable {
        private final String id;
        private final long timeout;

        Task(String id, long timeout) {
            this.id = id;
            this.timeout = timeout;
        }

        @Override
        public void run() {
            System.out.printf("%s : start : timeout = %d sec. : permits = %d%n",
                    id, timeout, semaphore.availablePermits());
            try {
                if (semaphore.tryAcquire(timeout, TimeUnit.SECONDS)) {
                    try {
                        System.out.printf("%s : try acquire = true (%f sec.)%n",
                                id, elapsedTime.getAsDouble());

                        TimeUnit.SECONDS.sleep(3);
                        System.out.printf("%s : sleep completed : release! (%f sec.)%n",
                                id, elapsedTime.getAsDouble());
                    } finally {
                        semaphore.release();
                    }
                } else {
                    System.out.printf("%s : try acquire = false : Timeout! (%f sec.)%n",
                            id, elapsedTime.getAsDouble());
                }
            } catch (InterruptedException e) {
                System.out.println("InterruptedException!");
            }
        }
    }

    executor.submit(new Task("A", 1));
    TimeUnit.MILLISECONDS.sleep(100);

    executor.submit(new Task("B", 2));
    TimeUnit.MILLISECONDS.sleep(100);

    executor.submit(new Task("C", 5));
}

System.out.println("-- all tasks end --");
System.out.println("permits : " + semaphore.availablePermits());

// Result
// ↓
//A : start : timeout = 1 sec. : permits = 1
//A : try acquire = true (0.003326 sec.)
//B : start : timeout = 2 sec. : permits = 0
//C : start : timeout = 5 sec. : permits = 0
//B : try acquire = false : Timeout! (2.116379 sec.)
//A : sleep completed : release! (3.007164 sec.)
//C : try acquire = true (3.007721 sec.)
//C : sleep completed : release! (6.021869 sec.)
//-- all tasks end --
//permits : 1

Related posts

To top of page