Java ReentrantLock lock with multiple conditions

Introduction

A lock may be associated with one or more conditions.

These conditions are declared in the Condition interface.


import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
  public static void main(String[] args) {
    ContentReader contentReader = new ContentReader(101, 10);
    Buffer buffer = new Buffer(20);
    Thread threadProducer = new Thread(new Producer(contentReader, buffer), "Producer");
 
    Thread threadConsumers[] = new Thread[3];

    for (int i = 0; i < 3; i++) {
      threadConsumers[i] = new Thread(new Consumer(buffer), "Consumer " + i);
    }//from ww  w .j  ava  2s .c  o  m

    threadProducer.start();
    for (int i = 0; i < 3; i++) {
      threadConsumers[i].start();
    }
  }

}

class Buffer {
  private LinkedList<String> buffer = new LinkedList<>();
  private int maxSize;
  private ReentrantLock lock = new ReentrantLock();
  private Condition lines = lock.newCondition();
  private Condition space;
  private boolean pendingLines = true;

  public Buffer(int maxSize) {
    this.maxSize = maxSize;
    space = lock.newCondition();
  }

  public void insert(String line) {
    lock.lock();
    try {
      while (buffer.size() == maxSize) {
        space.await();
      }
      buffer.offer(line);
      System.out.printf("%s: Inserted Line: %d\n", Thread.currentThread().getName(), buffer.size());
      lines.signalAll();
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
  }

  public String get() {
    String line = null;
    lock.lock();
    try {
      while ((buffer.size() == 0) && (hasPendingLines())) {
        lines.await();
      }
      if (hasPendingLines()) {
        line = buffer.poll();
        System.out.printf("%s: Line Readed: %d\n", Thread.currentThread().getName(), buffer.size());
        space.signalAll();
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
    return line;
  }

  public void setPendingLines(boolean pendingLines) {
    this.pendingLines = pendingLines;
  }

  public boolean hasPendingLines() {
    return pendingLines || buffer.size() > 0;
  }

}

class Consumer implements Runnable {
  private Buffer buffer;

  public Consumer(Buffer buffer) {
    this.buffer = buffer;
  }

  @Override
  public void run() {
    while (buffer.hasPendingLines()) {
      String line = buffer.get();
      processLine(line);
    }
  }

  private void processLine(String line) {
    try {
      Random random = new Random();
      Thread.sleep(random.nextInt(100));
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

}

class Producer implements Runnable {
  private ContentReader contentReader;
  private Buffer buffer;

  public Producer(ContentReader c, Buffer buffer) {
    this.contentReader = c;
    this.buffer = buffer;
  }

  @Override
  public void run() {
    buffer.setPendingLines(true);
    while (contentReader.hasMoreLines()) {
      String line = contentReader.getLine();
      buffer.insert(line);
    }
    buffer.setPendingLines(false);
  }

}

class ContentReader {

  private String content[];

  private int index;

  public ContentReader(int size, int length) {
    content = new String[size];
    for (int i = 0; i < size; i++) {
      StringBuilder buffer = new StringBuilder(length);
      for (int j = 0; j < length; j++) {
        int indice = (int) Math.random() * 255;
        buffer.append((char) indice);
      }
      content[i] = buffer.toString();
    }
    index = 0;
  }
  public boolean hasMoreLines() {
    return index < content.length;
  }
  public String getLine() {
    if (this.hasMoreLines()) {
      System.out.println("Mock: " + (content.length - index));
      return content[index++];
    }
    return null;
  }

}



PreviousNext

Related