A semaphore controls the number of threads that can access a resource.
A synchronized block allows only one thread to access a resource, whereas a semaphore allows N threads to access a resource.
If N is one, a semaphore is acting as a synchronized block.
Suppose there is a restaurant with three dining tables.
A person must take a token for a table.
After eating, he will return the token.
If no token is available he must wait.
Semaphore class from java.util.concurrent package represents the semaphore synchronizer.
You create a semaphore as follows:
final int MAX_PERMITS = 3; Semaphore s = new Semaphores(MAX_PERMITS);
To create a fair Semaphore
Semaphore s = new Semaphores(MAX_PERMITS, true); // A fair semaphore
A fair semaphore will guarantee first come first serve.
To acquire a permit, use the acquire() method.
It returns immediately if a permit is available. It blocks if a permit is not available.
To release a permit, use the release() method.
import java.util.Random; import java.util.concurrent.Semaphore; public class Main { public static void main(String[] args) { // Create a restaurant with three dining tables Restaurant restaurant = new Restaurant(3); // Create five customers for (int i = 1; i <= 5; i++) { RestaurantCustomer c = new RestaurantCustomer(restaurant, i); c.start();// w w w . j av a2 s. co m } } } class Restaurant { private Semaphore tables; public Restaurant(int tablesCount) { this.tables = new Semaphore(tablesCount); } public void getTable(int customerID) throws Exception{ System.out.println("Customer #" + customerID + " is trying to get a table."); tables.acquire(); System.out.println("Customer #" + customerID + " got a table."); } public void returnTable(int customerID) { System.out.println("Customer #" + customerID + " returned a table."); tables.release(); } } class RestaurantCustomer extends Thread { private Restaurant r; private int customerID; public RestaurantCustomer(Restaurant r, int customerID) { this.r = r; this.customerID = customerID; } public void run() { try { r.getTable(this.customerID); // Get a table int eatingTime = 3; System.out.println("Customer #" + this.customerID + " will eat for " + eatingTime + " seconds."); Thread.sleep(eatingTime * 1000); System.out.println("Customer #" + this.customerID + " is done eating."); } catch (Exception e) { e.printStackTrace(); } finally { r.returnTable(this.customerID); } } }