Java Exchanger change data between concurrent tasks

Introduction

The Java Exchanger class allows the interchange of data between two concurrent tasks.

Exchanger can create a synchronization point between two threads.

When the two threads arrive to this point, they interchange a data structure.

As the Exchanger class only synchronizes two threads, you can use it if you have a producer-consumer problem with one producer and one consumer.

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Exchanger;

public class Main {
  public static void main(String[] args) {
    List<String> buffer1 = new ArrayList<>();
    List<String> buffer2 = new ArrayList<>();

    Exchanger<List<String>> exchanger = new Exchanger<>();

    Producer producer = new Producer(buffer1, exchanger);
    Consumer consumer = new Consumer(buffer2, exchanger);

    Thread threadProducer = new Thread(producer);
    Thread threadConsumer = new Thread(consumer);

    threadProducer.start();/*from w ww.j a va  2 s . c o m*/
    threadConsumer.start();
  }
}

class Consumer implements Runnable {
  private List<String> buffer;
  private final Exchanger<List<String>> exchanger;

  public Consumer(List<String> buffer, Exchanger<List<String>> exchanger) {
    this.buffer = buffer;
    this.exchanger = exchanger;
  }

  @Override
  public void run() {
    int cycle = 1;

    for (int i = 0; i < 10; i++) {
      System.out.printf("Consumer: Cycle %d\n", cycle);
      try {
        buffer = exchanger.exchange(buffer);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }

      System.out.printf("Consumer: %d\n", buffer.size());

      for (int j = 0; j < 10; j++) {
        String message = buffer.get(0);
        System.out.printf("Consumer: %s\n", message);
        buffer.remove(0);
      }
      cycle++;
    }
  }
}

class Producer implements Runnable {
  private List<String> buffer;
  private final Exchanger<List<String>> exchanger;

  public Producer(List<String> buffer, Exchanger<List<String>> exchanger) {
    this.buffer = buffer;
    this.exchanger = exchanger;
  }

  @Override
  public void run() {
    int cycle = 1;

    for (int i = 0; i < 10; i++) {
      System.out.printf("Producer: Cycle %d\n", cycle);

      for (int j = 0; j < 10; j++) {
        String message = "Event " + ((i * 10) + j);
        System.out.printf("Producer: %s\n", message);
        buffer.add(message);
      }

      try {
        buffer = exchanger.exchange(buffer);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }

      System.out.printf("Producer: %d\n", buffer.size());

      cycle++;
    }
  }
}



PreviousNext

Related