Custom Implementation of Semaphore in Java
Let’s build our own version of Semaphore step-by-step.
Step 1 — Plan the Logic
Our custom semaphore needs:
- A permit count initialized during construction.
- A mechanism to let threads wait (wait() / notifyAll()).
- acquire() and release() methods to manage permits.
Step 2 — Create CustomSemaphore Class
public class CustomSemaphore {
private int permits;
public CustomSemaphore(int permits) {
if (permits < 0) throw new IllegalArgumentException("Permits cannot be negative");
this.permits = permits;
}
public synchronized void acquire() throws InterruptedException {
while (permits <= 0) {
wait();
}
permits--;
}
public synchronized void release() {
permits++;
notifyAll();
}
public synchronized int availablePermits() {
return permits;
}
}
Step 3 — Test CustomSemaphore
public class CustomSemaphoreTest {
public static void main(String[] args) {
CustomSemaphore semaphore = new CustomSemaphore(2);
Runnable task = () -> {
try {
System.out.println(Thread.currentThread().getName() + " is waiting for a permit.");
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " acquired a permit.");
Thread.sleep(2000); // simulate resource usage
System.out.println(Thread.currentThread().getName() + " releasing permit.");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
for (int i = 0; i < 5; i++) {
new Thread(task).start();
}
}
}
Expected Output
Thread-0 is waiting for a permit.
Thread-0 acquired a permit.
Thread-1 is waiting for a permit.
Thread-1 acquired a permit.
Thread-2 is waiting for a permit.
Thread-3 is waiting for a permit.
Thread-4 is waiting for a permit.
Thread-0 releasing permit.
Thread-2 acquired a permit.
Thread-1 releasing permit.
Thread-3 acquired a permit.
...
ore Example
// Step 1 & 2 — Custom Semaphore Implementation
class CustomSemaphore {
private int permits;
// Constructor to initialize permits
public CustomSemaphore(int permits) {
if (permits < 0) {
throw new IllegalArgumentException("Permits cannot be negative");
}
this.permits = permits;
}
// Acquire a permit — waits if none are available
public synchronized void acquire() throws InterruptedException {
while (permits <= 0) {
wait();
}
permits--;
}
// Release a permit and notify waiting threads
public synchronized void release() {
permits++;
notifyAll();
}
// Returns number of currently available permits
public synchronized int availablePermits() {
return permits;
}
}
// Step 3 — Test the Custom Semaphore
public class CustomSemaphoreTest {
public static void main(String[] args) {
// Create semaphore with 2 permits
CustomSemaphore semaphore = new CustomSemaphore(2);
// Define a task that uses the semaphore
Runnable task = () -> {
try {
System.out.println(Thread.currentThread().getName() + " is waiting for a permit.");
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " acquired a permit.");
// Simulate resource usage
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " releasing permit.");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
// Create and start 5 threads sharing the same semaphore
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(task);
thread.start();
}
}
}
✅ How to Run
- Save the file as CustomSemaphoreTest.java.
Compile it:
javac CustomSemaphoreTest.javaRun it:
java CustomSemaphoreTest
