Java Semaphore control concurrent access to multiple copies of a resource

Introduction

The following code shows how to use a semaphore to protect more than one copy of a resource.


import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
  public static void main(String args[]) {
    SharedResource printQueue = new SharedResource();
    // Creates ten Threads
    Thread thread[] = new Thread[12];
    for (int i = 0; i < 12; i++) {
      thread[i] = new Thread(new Job(printQueue), "Thread " + i);
    }/*from  w w w .  jav a 2  s.c o  m*/
    // Starts the Threads
    for (int i = 0; i < 12; i++) {
      thread[i].start();
    }
  }
}

class Job implements Runnable {
  private SharedResource printQueue;
  public Job(SharedResource printQueue) {
    this.printQueue = printQueue;
  }

  @Override
  public void run() {
    System.out.printf("%s: Going to print a job\n", Thread.currentThread().getName());
    printQueue.printJob(new Object());
    System.out.printf("%s: The document has been printed\n", Thread.currentThread().getName());
  }
}

/**
 * This class have access to three printers.
 */
class SharedResource {

  private Semaphore semaphore = new Semaphore(3);

  private boolean[] freePrinters = new boolean[] {true,true,true};

  private Lock lockPrinters = new ReentrantLock();

  public void printJob(Object document) {
    try {
      // Get access to the semaphore. 
      semaphore.acquire();

      // Get the number of the free printer
      int assignedPrinter = getPrinter();

      Long duration = (long) (Math.random() * 10);
      System.out.println(Thread.currentThread().getName()+"/"+ assignedPrinter+" for "+ duration);
      TimeUnit.SECONDS.sleep(duration);

      // Free the printer
      freePrinters[assignedPrinter] = true;
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      // Free the semaphore
      semaphore.release();
    }
  }

  private int getPrinter() {
    int ret = -1;

    try {
      // Get the access to the array
      lockPrinters.lock();
      // Look for the first free printer
      for (int i = 0; i < freePrinters.length; i++) {
        if (freePrinters[i]) {
          ret = i;
          freePrinters[i] = false;
          break;
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      // Free the access to the array
      lockPrinters.unlock();
    }
    return ret;
  }

}



PreviousNext

Related