Using a reentrant lock to prevent multiple threads from accessing the same code - Java Thread

Java examples for Thread:Lock

Description

Using a reentrant lock to prevent multiple threads from accessing the same code

Demo Code

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main {

  Set<Thread> orderingThreads = new HashSet<>();
  Lock inventoryLock = new ReentrantLock();

  public static void main(String[] args) throws InterruptedException {
    Main recipe = new Main();
    recipe.start();//  ww  w . j a v  a2 s. c om
  }

  final Map<String, Integer> inventoryMap = new LinkedHashMap<>();
  List<CustomerOrder> customerOrders = new ArrayList<>();
  Random random = new Random();

  private void start() throws InterruptedException {
    for (int i = 0; i < 100; i++) {
      inventoryMap.put("Book #" + i, 1000);
    }
    for (int i = 0; i < 20; i++) {
      createOrderingThread();
    }
    Thread.sleep(100);
    checkInventoryLevels();
    Thread.sleep(100);
    orderingThreads.stream().forEach((thread) -> {
      thread.interrupt();
    });
    Thread.sleep(1000);
    checkInventoryLevels();
    displayOrders();
  }

  private void displayOrders() {
    try {
      inventoryLock.lock();
      customerOrders.stream().forEach(
          (order) -> {
            System.out.println(order.getItemOrdered());
          });
    } finally {
      inventoryLock.unlock();
    }
  }

  private void createOrderingThread() {
    Thread orderingThread = new Thread(() -> {
      while (!Thread.interrupted()) {
        createRandomOrder();
      }
    });
    orderingThread.start();
    orderingThreads.add(orderingThread);

  }

  private void createRandomOrder() {
    String itemOrdered = "Book #" + random.nextInt(100);
    int quantityOrdered = random.nextInt(2) + 1;
    String customerName = "Customer :" + UUID.randomUUID().toString();
    fulfillOrder(itemOrdered, quantityOrdered, customerName);
  }

  private boolean fulfillOrder(String itemOrdered, int quantityOrdered,
      String customerName) {
    try {
      inventoryLock.lock();
      int currentInventory = inventoryMap.get(itemOrdered);
      if (currentInventory < quantityOrdered) {
        System.out.println("Couldn't fulfill order for " + customerName
            + " not enough " + itemOrdered + " (" + quantityOrdered + ")");
        return false; // sorry, we sold out
      }
      inventoryMap.put(itemOrdered, currentInventory - quantityOrdered);
      CustomerOrder order = new CustomerOrder(itemOrdered);
      customerOrders.add(order);
      System.out.println("Order fulfilled for " + customerName + " of "
          + itemOrdered + " (" + quantityOrdered + ")");
      return true;
    } finally {
      inventoryLock.unlock();
    }
  }

  private void checkInventoryLevels() {
    try {
      inventoryLock.lock();
      inventoryMap
          .entrySet()
          .stream()
          .forEach(
              (inventoryEntry) -> {
                System.out.println("Inventory Level :"
                    + inventoryEntry.getKey() + " " + inventoryEntry.getValue());
              });
    } finally {
      inventoryLock.unlock();
    }
  }

}

class CustomerOrder {
  String itemOrdered;
  CustomerOrder(String itemOrdered) {
    this.itemOrdered = itemOrdered;
  }
  public String getItemOrdered() {
    return itemOrdered;
  }
}

Result


Related Tutorials