One Producer, multiple Consumers - java

I have been working on some code, but I need help.
I have created one producer and one consumer, however I need to create multiple consumers who will consume the specific String from the producer e.g. I need a consumer that will consume specifically 'Move Left Hand'.
Contained in the code is the buffer, producer, consumer and the main. I am not sure how to notify the correct consumer and compare the string that needs to be consumed. As it stands I only have one consumer.
public class iRobotBuffer {
private boolean empty = true;
public synchronized String take() {
// Wait until message is
// available.
while (empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = true;
// Notify producer that
// status has changed.
notifyAll();
return message;
}
public synchronized void put(String message) {
// Wait until message has
// been retrieved.
while (!empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = false;
// Store message.
this.message = message;
// Notify consumer that status
// has changed.
notifyAll();
}
}
public class iRobotConsumer implements Runnable {
private iRobotBuffer robotBuffer;
public iRobotConsumer(iRobotBuffer robotBuffer){
this.robotBuffer = robotBuffer;
}
public void run() {
Random random = new Random();
for (String message = robotBuffer.take();
! message.equals("DONE");
message = robotBuffer.take()) {
System.out.format("MESSAGE RECEIVED: %s%n", message);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
}
}
public class iRobotProducer implements Runnable {
private iRobotBuffer robotBuffer;
private int number;
public iRobotProducer(iRobotBuffer robotBuffer)
{
this.robotBuffer = robotBuffer;
//this.number = number;
}
public void run() {
String commandInstructions[] = {
"Move Left Hand",
"Move Right Hand",
"Move Both Hands",
};
int no = commandInstructions.length;
int randomNo;
Random random = new Random();
for (int i = 0;
i < commandInstructions.length;
i++) {
randomNo =(int)(Math.random()*no);
System.out.println(commandInstructions[randomNo]);
robotBuffer.put(commandInstructions[i]);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
robotBuffer.put("DONE");
}
}
public class iRobot
{
public static void main(String[] args)
{
iRobotBuffer robotBuffer = new iRobotBuffer();
(new Thread(new iRobotProducer(robotBuffer))).start();
(new Thread(new iRobotConsumer(robotBuffer))).start();
}//main
}//class

The problem is your iRobotBuffer class. It needs to be a queue to support multiple producer / consumers. I've provided the code for such a queue, but java already has an implementation (BlockingDeque<E>).
public class BlockingQueue<T> {
private final LinkedList<T> innerList = new LinkedList<>();
private boolean isEmpty = true;
public synchronized T take() throws InterruptedException {
while (isEmpty) {
wait();
}
T element = innerList.removeFirst();
isEmpty = innerList.size() == 0;
return element;
}
public synchronized void put(T element) {
isEmpty = false;
innerList.addLast(element);
notify();
}
}

As I understand, you would like 3 consumers, one for each move instruction.
You can use an ArrayBlockingQueue from the java.util.concurrent package, in place of the iRobotBuffer class. By the way, you can have a look at the other concurrent collections provided - one may sweet you better.
Then for the consumer, you can peek() at what is in the queue and test if it matches the requirements and then poll().

Related

How to control child-thread lifecycle and synchonize it with main-thread?

I am trying to create another thread that processes data while main thread doing some more. Main thread must wait till another thread finishes doStuff with all elements.
And my implementation is pretty straight forward.
Please, take a look at processData and tell me is there some more Java-like way to do it?
I read about Phaser but still can't imagine how to use it or what else can I try?
public class MyClass {
private final NodeQueue queue;
MyClass() {
queue = new NodeQueue();
}
public void processData(Set<String> dataSet) {
// allow transfer
queue.transferEnable()
Thread transfer = new Thread(() -> {
queue.transferData();
})
transfer.start();
// doStuff in another thread
for (String element : dataSet) {
queue.add(element);
// do something more
}
// stop transfer
queue.waitTillEmptyQueue();
queue.transferDisable();
try {
transfer.join();
} catch (...) {
// catch
}
}
public class NodeQueue {
private final ConcurrentLinkedQueue<String> queue;
private boolean transferEnabled;
protected NodeQueue() {
queue = new ConcurrentLinkedQueue<>();
transferEnabled = true;
}
protected void transfer() {
while (!queue.isEmpty()) {
doStuff(queue.poll());
}
}
public void transferData() {
while (tranfserEnabled) {
transfer();
}
}
public synchronized void transferEnable() {
transferEnabled = true;
}
public synchronized void transferDisable() {
transferEnabled = false;
}
public void add(String s) {
queue.add(s);
}
public synchronized void waitTillEmptyQueue() {
while (!queue.isEmpty()) {
if (queue.isEmpty()) {
break;
}
}
}
}
}
Let me copy the Phaser example from my own post
Main thread
// Add producer as a party
Phaser phaser = new Phaser(1);
for (int i=0; i<10000; ++i) {
// Add each task as a party
phaser.register();
queue.put(new Task());
}
// Producer arrived and wait for completion of all tasks
phaser.arriveAndAwaitAdvance();
// At the end, there is only 1 party left which is the producer itself
Consumer
while (true) {
Task task = queue.take();
processTask(task);
// Task completed and remove itself as a party
phaser.arriveAndDeregister();
}

How to synchronize three producers and one consumer threads in java

I have to make three producers and one consumer thread. Producers threads is reading chars from file and using buffer of one char. I made Store like above, now i have to synchronize threads to consumer write whole word and give back control to other producer - patern like this
Producer1->Word1
Producer2->word1
Producer3->word1
Producer1->Word2
Producer2->word2
Producer3->word2
Producer1->Word3
Producer2->word3
Producer3->word3
Store (edited):
public class Store {
public static final char CONSUMER_FREE = '\0';
private volatile char consumer = CONSUMER_FREE;
private final ThreadPoolExecutor executor;
public Store(ThreadPoolExecutor executor) {
this.executor = executor;
}
public synchronized void produce(char c) {
while (isConsumerBussy()) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
consumer = c;
notify(); // single Consumer
}
public synchronized char consume() throws StoreProducersRip {
while (isConsumerFree()) {
try {
wait(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
return consumer;
} finally {
freeConsumer();
notifyAll();
}
}
private void freeConsumer() {
consumer = CONSUMER_FREE;
}
private boolean isConsumerBussy() {
return consumer != CONSUMER_FREE;
}
private boolean isConsumerFree() throws StoreProducersRip {
if (executor.getActiveCount() == 0) throw new StoreProducersRip();
return consumer == CONSUMER_FREE;
}
}
You can use locks for this purpose. Below code demonstrates 3 producer synchronous and 1 consumer async to producers but it'd also be sync to multiple consumers here. Also you should add some logic to consume same amount that produced. If you want to get benefits of multithreading, you should buffer your producer input and create some pipeline before consuming.
public class Executor {
public static void main(String[] args) {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
Store store = new Store(executor);
Runnable word1 = new Runnable() {
#Override
public void run() {
store.producerLock.lock();
store.produce('1');
store.produce('2');
store.produce('3');
store.producerLock.unlock();
}
};
Runnable consume = new Runnable() {
#Override
public void run() {
store.consumerLock.lock();
System.out.print(store.consume());
System.out.print(store.consume());
System.out.print(store.consume());
System.out.println();
store.consumerLock.unlock();
}
};
Future p1 = executor.submit(word1);
Future p2 = executor.submit(word1);
Future p3 = executor.submit(word1);
executor.submit(consume);
executor.submit(consume);
executor.submit(consume);
executor.shutdown();
}
}

Implementing a Semaphore with a Queue

I am trying to create a basic Semaphore implementation using Queue. The idea is, there is a database, and there are 10 writers. Writers can only write to the database in mutual exclusion. I am using Queue because I want to implement First In First Out and Last In First Out.
Using Semaphore, I can't notify a specific thread to wake up. So my idea is what I am doing is for every Writer, I create an object and tell the Writer to wait on that object. Puts that object in a queue. Then remove the object from the queue and notify the Thread that is waiting on that object. In this way, I think I can make a FIFO or LIFO implementation.
I need help on the actual code implementation:
1. I run the code below, it gave me a lot of IllegalMonitorStateException.
2. FIFO and LIFO code (my FIFO code seems incorrect, while for LIFO code, I'm thinking to use Stack instead of Queue).
public class Test {
public static void main(String [] args) {
Database db = new Database();
for (int i = 0; i < 10; i++)
(new Thread(new Writer(db))).start();
}
}
public class Writer implements Runnable {
private Database database;
public Writer(Database database) {
this.database = database;
}
public void run() {
this.database.acquireWriteLock();
this.database.write();
this.database.releaseWriteLock();
}
}
public class Database {
private Semaphore lockQueue;
public Database() {
this.lockQueue = new Semaphore();
}
public void write() {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {}
}
public void acquireWriteLock() {
lockQueue.acquire();
}
public void releaseWriteLock() {
lockQueue.release();
}
}
import java.util.Queue;
import java.util.LinkedList;
public class Semaphore {
private Queue<Object> queue;
public Semaphore() {
this.queue = new LinkedList<Object>();
}
public synchronized void acquire() {
Object object = new Object();
try {
if (this.queue.size() > 0) {
object.wait();
this.queue.add(object);
}
} catch (InterruptedException ie) {}
this.queue.add(object);
}
public synchronized void release() {
Object object = this.queue.remove();
object.notify();
}
}
You need to acquire the lock of the object before you can use wait() and notify().
Try to check if the following code will work:
public class Semaphore {
private Queue<Object> queue;
private int state;
public Semaphore() {
this.queue = new LinkedList<Object>();
}
public void acquire() {
Object object = new Object();
synchronized (object) {
try {
if (this.state > 0) {
this.queue.add(object);
object.wait();
} else {
state++;
}
} catch (InterruptedException ie) {
}
}
}
public void release() {
Object object = this.queue.poll();
state--;
if(null == object) {
return;
}
synchronized (object) {
object.notify();
}
}
}

end consumer thread after producer thread and consuming all the elements

I have written code to implement producer consumer problem using wait and notify. It is working fine but the problem is consumer thread is running in an infinite loop and keeps on waiting even after producer thread has finished and consumer has consumed all the elements from list.
public class Practice {
public static void main(String[] args) {
List<Employee> empList = new ArrayList<Employee>();
Thread producer = new Thread(new Producer(empList , 2) , "Producer");
Thread consumer = new Thread(new Consumer(empList , 2) , "Consumer");
producer.start();
consumer.start();
}
}
class Employee
{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Producer implements Runnable
{
List<Employee> empList;
int size;
public Producer(final List<Employee> empList , final int size)
{
this.empList = empList;
this.size = size;
}
#Override
public void run()
{
for(int i=0; i<5;i++)
{
try {
produce(new Employee());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void produce(Employee e) throws InterruptedException
{
synchronized(empList){
while(empList.size()==size) // If list is full then will have to wait
{
System.out.println("List is full "+Thread.currentThread().getName()+" Is waiting and" + " Size is "+empList.size());
empList.wait();
}
}
synchronized(empList)
{
System.out.println("Producing");
empList.add(e);
empList.notifyAll();
}
}
}
class Consumer implements Runnable
{
List<Employee> empList;
int size;
public Consumer(final List<Employee> empList , final int size)
{
this.empList = empList;
this.size = size;
}
#Override
public void run()
{
while(true)
{
try {
System.out.println("Consumed ");
consume();
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void consume() throws InterruptedException
{
synchronized(empList){
while(empList.isEmpty()) // If list is empty then will have to wait
{
System.out.println("List is empty "+Thread.currentThread().getName()+" Is waiting and " + "Size is "+empList.size());
empList.wait();
}
}
synchronized(empList)
{
empList.notifyAll();
empList.remove(0);
}
}
}
Kindly tell me how can I stop my consumer thread after producer finishes and consumer has consumed all the elements from list. Please help me with the code. Thanks in advance
Just add flag, shared between producer and consumer:
static bool producerFinished = false;
Set it in the producer after it produce all elements:
public void run()
{
// ...
synchronized(empList){
producerFinished = true;
empList.notifyAll();
}
}
And check it in the consumer's while() loop alongside with list emptiness
public void consume()
{
synchronized(empList){
while(empList.isEmpty() && !producerFinished)
{
empList.wait();
}
if(!empList.isEmpty())
{
//consume element
}
else
{
//List is empty and producer has finished.
}
}
}
A producer-consumer idiom for this is the Poison Pill pattern: the producer puts a magic value in the queue when finished producing, then quits. When the consumer reads the magic value, it quits.
Poison pill definition is shared between producer and consumer:
static final Employee POISON_PILL = new Employee();
Producer:
public void run()
{
for(int i=0; i<5;i++)
{
produce(new Employee());
}
produce(POISON_PILL);
}
Consumer:
public void consume() throws InterruptedException
{
synchronized(empList){
while(empList.isEmpty())
{
empList.wait();
}
}
synchronized(empList)
{
// Note == not .equals() is intended here
if (empList.remove(0) == POISON_PILL) {
// done consuming
}
empList.notifyAll();
}
}

Java Simple Concurrent Server

I must design a simple server which receives messages from multiple nodes and stores them in a message repository.
The code for the server is :
public class CommunicationServer implements Runnable {
private List<String> messages;
private MessageRepository messageRepository;
private boolean serverBusy;
public CommunicationServer() {
messages = new ArrayList<String>();
messageRepository = new MessageRepository();
serverBusy = false;
}
#Override
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
if (messages.size() > 10) {
serverBusy = true;
addMessageToRepository();
notifyAll();
}
else {
serverBusy = false;
wait();
}
}
}
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
public synchronized void receiveMessage(String message) {
if (messages.size() < 10) {
messages.add(message);
}
}
private void addMessageToRepository() {
if (messages.size() != 0) {
messageRepository.addMessage(messages.remove(0));
}
}
public void showMessageRepository() {
messageRepository.showStoredMessages();
}
public synchronized boolean isServerBusy() {
return serverBusy;
}
}
The code for the node is:
public class Node implements Runnable {
private static final String CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ0123456789";
private static final int MESSAGE_LENGHT = 5;
private Random random = new Random();
private CommunicationServer communicationServer;
public Node(CommunicationServer communicationServer) {
this.communicationServer = communicationServer;
}
#Override
public void run() {
try {
while (!Thread.interrupted()) {
while (communicationServer.isServerBusy()) {
wait();
}
communicationServer.receiveMessage(generateRandomString());
}
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
private String generateRandomString() {
StringBuffer randomMessage = new StringBuffer();
for (int i = 0; i < MESSAGE_LENGHT; i++) {
randomMessage.append(CHARACTERS.charAt(random.nextInt(51)));
}
return randomMessage.toString();
}
}
In main I just create a thread for the server and 5 threads for the nodes and let them run for some time. The server sleeps until it receives 10 messages, after that it must wake up to process the messages. The problem is I can't figure it out where to call notifyAll() in order to wake the thread responsible for the server.
Making CommunicationServer implements Runnable doesn't really make sense and exposes your basic misunderstanding: you identify the actors in your process (server, client) with threads. A thread is not the actor; a thread is where actor's code gets executed.
So, when in your CommunicationServer you say wait(), you don't make the server wait for messages; you make that particular thread wait on the server object as its monitor. Likewise, then you say notifyAll(), you are not "notifying all servers"; you are notifying all threads waiting on that particular monitor. It should be some code in the client which notifies the threads that are currently waiting on the server's monitor, and some code in the server which notifies those waiting on the client monitor.
As a general rule of thumb, when you find yourself using both wait() and notify() within the same synchronized block, you can be pretty sure there's something wrong with your logic.

Categories