java - producer consumer pattern finish signal - java

I have an application which applies the Producer-Consumer design pattern. IT is written in java. in short, the producers put items in a blocking queue and the consumers takes them from there. the consumers should run until signaled by a producer to stop.
what is the neatest way to deliver this signal from producers to the consumers? the chief designer said he wants to keep producer and consumer separate but I dont see any other other than invoking a method on consumer thread pool?

The Chief Programmer is right. Keeping them separate leads to highly decoupled code which is excellent.
There are several ways to do this. One of them is called Poison Pill. Here's how it works - place a known item on the Queue when the Consumer see that item, they kill themselves or take another action.
This can be tricky if there are multiple Consumers (you mentioned ThreadPool) or bounded Queues. Please look this up in Java Concurrency in Practice by Joshua Bloch. He explained it best.

Send a cancel message through the queue. Your consumers' run methods would look like
while(true) {
Message message = queue.take();
if(message == Message.Cancel) {
queue.offer(message); // so that the other consumers can read the Cancel message
break;
}
}

Create a ConsumerHalter class. Register all consumers that wants to get data from queue to the ConsumerHalter class, and have producer trigger a halt event in the ConsumerHalther class. The ConsumerHalter class then calls onStopConsuming() of each consumers.

Related

java multithread: How to know when a consumer thread should remove an element from queue

I have a producer consumer model which an arduino generates packets and inside my pc I have a java program which takes those packets and puts them into a BlockingQueue. Now there are threads that process these packets.
Let's say X is producer and A, B and C are consumers thread. there is a queue which all consumers have reference to it. Messages(packets) are immutable objects (i.e. consumers can't change the state of the elements). My question is How can I know all threads are done with specific element inside queue so I can remove it?
here is my consumer run() method:
#Override
public void run()
{
while (isStarted && !queue.isEmpty()) {
updateMap(queue.peek());
}
}
One design I'm thinking of is to use a bounded queue. When producer finds out queue is full then it removes the first element. But I'm not sure if this is a safe approach. I read this tutorial and a few more and what I get is:
Producer should wait if Queue or bucket is full and Consumer should wait if queue or
bucket is empty.
I'm sorry if it sounds obvious, but I'm new to multithread programming and the concurrency nature of code sounds scary to me.
EDIT:
All A, B and C do independently. One is for Statistics one for updating network map etc.
EDIT 2:
As #Augusto sugested there is another approach which each of A, B and C has their own queue. My network listener passes the packets to each queue and they process it. It works but How can I do this with only one queue? or is it possible to implement this scenario using only one queue? and if the answer is yes. How and when I need to remove element from queue?
(a follow up on my comment after your edit) I would suggest to have a different queue per thread. This is actually a very well know pattern called publish-subscribe.
Taken from the link above:
A Publish-Subscribe Channel works like this: It has one input channel
that splits into multiple output channels, one for each subscriber.
When an event is published into the channel, the Publish-Subscribe
Channel delivers a copy of the message to each of the output channels.
Each output channel has only one subscriber, which is only allowed to
consume a message once. In this way, each subscriber only gets the
message once and consumed copies disappear from their channels.
The main difference between a ConcurrentLinkedQueue and a BlockingQueue is that you can add a limit on how many elements are on the BlockingQueue. This is good in the case that the producer reading from the network generates data faster than the consumers can process. If you use an unbounded queue and this goes for a while you'll end up with an OutOfMemoryError.

Java Synchronizers

Scenario - A Queue has message objects. The queue is polled and messages are passed to message handlers. The message retrieval (poll) should be halted on client login event (one or more). I could use a wait/notify mechanism to achive this, but the advice from Joshua Bloch says , there is hardly any reason to use the cumbersome wait/notify mechanism with the advent of concurrent utilities. I am unable to make a choice as to which synchronizers (semaphore, cyclic barrier, countdownlatch) will fit my purpose. Any advice appreciated.
If the termination need not be immediate, you could use a "poison pill" pattern. When a user logs in, place a special "termination" object on the Queue. When you poll the Queue, check for that special, unique object. e.g.
public static final Message POISON_PILL = new Message();
...
in your loop {
Message message = queue.take();
if (message == POISON_PILL) // note usage of == here!
stopTheQueue();
else
normalProcessing(message);
}
This means that the Queue will process all Messages that were present before the user logged in. Which may be what you want.
If the stoppage needs to be immediate, check for Thread.interrupted() As described here. This requires that the login handlers know which Thread is handling the Queue, increasing coupling. So the "poison pill" is nice in that it has less coupling.

rabbitMQ consume from 2 queues

I have to write heavy load system, with pretty easy task to do. So i decided to split this tasks into multiple workers in different locations (or clouds). To communicate i want to use rabbitmq queue.
In my system there will be two kinds of software nodes: schedulers and workers. Schedulers will take user input from queue_input, split it into smaller task and put this smaller task into workers_queue. Workers reads this queue and 'do the thing'. I used round-robbin load balancing here - and all works pretty well, as long, as some worker crashed. Then i loose information about task completion (it's not allowed to do single operation twice, each task contains a pack of 50 iterations of doing worker-code with diffirent data).
I consider something like technical_queue - another channel to scheduler-worker communication, and I wonder, how to design it in a good way. I used tutorials from rabbitmq page, so my worker thread looks like :
while(true) {
message = consume(QUEUE,...);
handle(message); //do 50 simple tasks in loop for data in message
}
How can i handle second queue? Another thread we some while(true) {} loop?, or is there a better sollution to this? Maybe should I reuse existing queue with topic exchange? (but i wanted to have independent way of communication, while handling the task, which may take some time.
You should probably take a look at spring-amqp (doc). I hate to tell you to add a layer but that spring library takes care of the threading issues and management of threads with its SimpleMessageListenerContainer. Each container goes to a queue and you can specify # of threads (ie workers) per queue.
Alternatively you can make your own using an ExecutorService but you will probably end up rewriting what SimpleMessageListenerContainer does. Also you just could execute (via OS or batch scripts) more processes and that will add more consumers to each queue.
As far as queue topology is concerned it is entirely dependent on business logic/concerns and generally less on performance needs. More often you had more queues for business reasons and more workers for performance reasons but if a queue gets backed up with the same type of message considering giving that type of message its own queue. What your describing sounds like two queues with multiple consumer on your worker queue.
Other than the threading issue and queue topology I'm not entirely sure what else you are asking.
I would recommend you create a second queue consumer
consumer1 -> queue_process
consumer2 -> queue_process
Both consumers should make listening to the same queue.
Greetings I hope will help

Handling producer thread when no consumers are ready

Suggestions on patterns for handling the following scenario:
A single thread that dispatches events to consumers. There is a 1:1 between each event and a consumer (each event is dispatched to a single consumer based on event/consumer id match).
Consumers process events at varying speeds and can consume events in configurable batch sizes (e.g. a consumer could consume 20 events at a time).
The producer thread should always be able to dispatch events to consumers that are capable of consuming. Each consumer maintains a queue of events it has consumed (possibly in batch) and processes these on its own thread, so the hand-off from producer to consumer is asynchronous.
If no consumers can consume at any point in time, what should happen to the dispatch thread?
yield() it
wait() & force consumers to call notify() on it
sleep() for a fixed time period
spin
Any reason to prefer one over the other?
Some pros & cons:
yield is simple
forcing consumers to call notify adds complexity
sleep for a fixed time would suit for non time sensitive requirements
spinning eats up a CPU, unnecessary unless we need as fast as possible event delivery
Any other considerations?
Another way you should consider would be writing it to a BlockingQueue. Let the queue manage requests sent without listeners.
Even better: write a Broker that owns a BlockingQueue and maintains a List of Consumers. Have the Broker notify the List of Consumers when a Producer sends a new Event.
I'd use the PropertyChangeListener and EventObject built into Java Beans since JDK 1.0 to do this in memory.
a) You could choose yield but depending on how good the environment is, this could essentially become a no-op. So this would essentially have the same result as spinning.
b) Sleep is an easy choice but then you should come up with how long to sleep. Doing sleep(0) also will not help as it will be same as doing (a)
The force of notification is more complicated but you have complete control of your flow.
Take a look at JMS. JMS is designed to handle exactly this kind of use case.
A full scale JMS installation might be overkill in your scenario – you don't provide enough information.

Topic-like concurrent queue in plain Java

Before I reinvent the wheel, is there a topic-like concurrent queue in plain Java? I have the following requirements:
Multiple readers/consumers
Multiple writers/producers
Every message must be consumed by every (active) consumer
After every consumer reads a message it should become garbage (i.e. no more references)
Writing to the queue should not be O(N) to the number of consumers
Concurrent, preferably non-blocking
Not JMS based: it's for a much lighter/embeddable environment
That's pretty much everything I need. Any pointers?
Basically you are talking about multiplexing, and no there isn't something in the standard lib but it is pretty simple to create one. Presuming that your clients aren't interested in messages published before they subscribe then you need a pool of queues for each consumer and publication simply offers the item to each queue:
public class Multiplexer<M> {
private final List<BlockingQueue<M>> consumers
= new CopyOnWriteArrayList<BlockingQueue<M>>();
public void publish(M msg) {
for (BlockingQueue<M> q : consumers) {
q.offer(msg);
}
}
public void addConsumer(BlockingQueue<M> consumer) {
consumers.add(consumer);
}
}
This version allows consumers to use whatever blocking queue implementation they might want. You could obviously provide a standard implementation and a nice interface for the client if you want.
the 3rd condition is not in plain java but you can use a nonblocking linked queue with a separate head for each consumer (you can rely on GC to collect the unreferenced nodes)
The simplest strategy is to pass a message to every consumer, I wouldn't have so many consumer that the number of consumers is important. You can add messages to dozens of consumers in a few micro-seconds.
One way to avoid this is to have a circular ring buffer with many readers. This is tricky to implement and means the consumers will be limited in the number of sources of message they can have.
Have just one pseudo-consumer and let the real consumers register with the pseudo-consumer. When a producer sends a message, the pseudo consumer wakes up and consumes the message. On consuming the message, the pseudo-consumer creates a separate Runnable for each real consumer registered with it and executes them on a thread-pool.

Categories