concurrent

Exchanger example passing logs to a background logger

With this example we are going to demonstrate how to create an Exchanger passing logs to a background logger. We have implemented a class, BackgroundLogger that implements the Runnable interface. In short the class is described below:

  • It consists of a static class LogEntry, that has three fields, a long time, an int value and a Stringbuilder, and a static class LogEntries, that has two fields, an array of specified LongEntry objects, and an int used field.
  • The BackgroundLogger class creates a final ExecutorService that uses a single worker thread, using newSingleThreadExecutor() API method of Executors. It also creates a final Exchanger of LogEntries, that is a synchronization point at which threads can pair and swap elements within pairs.
  • The classe’s constructor uses submit(Runnable task) method of the classse’s ExecutorService to submit this Runnable task for execution and return a Future representing the task.
  • The classe’s run() method, inheritted from the Runnable,  is overriden, using the @Override annotation. In this method the LogEntries of this task are exchanged, using the exchange(LogEntries x) API method of the task’s Exchanger. For each one of the logEntry objects used the delete(int start, int end) API method of the StringBuilder is used, in order to remove the used entries.
  • In order that the task stops it first uses its flush() method, where the Exchanger is used to exhange any used entries and then the shutdownNow() API method of ExecutorService is called, so that the task’s excecutor attempts to stop the task.

Let’s take a look at the code snippet that follows:  

import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class BackgroundLogger implements Runnable {
  static final int ENTRIES = 64;
 
  static class LogEntry {
    long time;
    int level;
    final StringBuilder text = new StringBuilder();
  }
 
  static class LogEntries {
    final LogEntry[] lines = new LogEntry[ENTRIES];
    int used = 0;
  }
 
  private final ExecutorService executor = Executors.newSingleThreadExecutor();
  final Exchanger<LogEntries> logEntriesExchanger = new Exchanger<LogEntries>();
  LogEntries entries = new LogEntries();
 
  BackgroundLogger() {
    executor.submit(this);
  }
 
  public StringBuilder log(int level) {
    try {

if (entries.used == ENTRIES)

  entries = logEntriesExchanger.exchange(entries);

LogEntry le = entries.lines[entries.used++];

le.time = System.currentTimeMillis();

le.level = level;

return le.text;
 
    } catch (InterruptedException e) {

throw new RuntimeException(e);
    }
  }
 
  public void flush() throws InterruptedException {
    if(entries.used > 0)

  entries = logEntriesExchanger.exchange(entries);
  }
 
  public void stop() {
    try {

flush();
    } catch (InterruptedException e) {

e.printStackTrace(); // use standard logging.
    }
    executor.shutdownNow();
  }
 
  @Override
  public void run() {
    LogEntries entries = new LogEntries();
    try {

while (!Thread.interrupted()) {

  entries = logEntriesExchanger.exchange(entries);


for (int i = 0; i < entries.used; i++) {


  bgLog(entries.lines[i]);


  entries.lines[i].text.delete(0, entries.lines[i].text.length());

  }

  entries.used = 0;

}
    } catch (InterruptedException ignored) {
 
    } finally {

System.out.println("Warn: logger stopping."); // use standard logging.
    }
  }
 
  private void bgLog(LogEntry line) {
    // log the entry to a file.
  }
}

 
This was an example of how to create an Exchanger passing logs to a background logger in Java.
 

Related Article:

Reference: The Exchanger and GC-less Java from our JCG partner Peter Lawrey at the Vanilla Java

Byron Kiourtzoglou

Byron is a master software engineer working in the IT and Telecom domains. He is an applications developer in a wide variety of applications/services. He is currently acting as the team leader and technical architect for a proprietary service creation and integration platform for both the IT and Telecom industries in addition to a in-house big data real-time analytics solution. He is always fascinated by SOA, middleware services and mobile development. Byron is co-founder and Executive Editor at Java Code Geeks.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button