I'm working on a producer-consumer pattern that should work with a queue. As usually a consumer Thread and a Producer thread, producer will add an item to the queue at certain times interval (from 3 to 5 seconds), consumer will wait to process it as soon as the queue isn't empty.
As a requirement the producer should and will produce items non-stop, which means if the queue is full, it will keep producing, and that's why I can't use BlockingQueue implementations as they either wait for the queue to have available space or throw exception.
My current implementation is the following
// consumer's Runnable
public void run() {
while(true) {
if(!queue.isEmpty()) {
currentItem = queue.poll();
process(currentItem);
}
}
}
This thread will keep looping even if no item has been produced by the producer Thread.
How is it done to wait until the producer add an item to the queue, and also what is a good Queue implementation with no cap-limit ?
Related
On Android I have a normal Consumer - Producer scenario:
Different producer thread can add object to the list in
different time
When a certain event (Trigger event) appens a
consumer start to keep element from the list (there is only one
thread consumer.
When the list is empty the consumer it stop to
keep element from the list
As soon as the list is not empty the
consumer must tale the element from the list
The consumer must
be fast to keep data, as soon as the element it inserted in the list
from the producer the consumer have to keep it
I have this
scenario in a singleton, and I have to stop thread only when the app
is shutdown.
*
One of the producer is sometimes the UI thread
*
What type of synchronization and list do you suggest to use ? I would do this without waste cpu load.
I'm scared of point 7.. i don't want to block for a lot of time the UI thread
EDIT : for add details for #Alex
I'm writing it in pseudocode:
Thread C producer : calls EventTracker.trackEvent( C )
UI producer : calls EventTracker.trackEvent( A )
EventTracker
{
BlockingQueue<Event> blockingQueue
trackEvent(Event x)
{
blockingQueue.offer(500, ms);
}
Thread consumer
{
while(true){
Event p = blockingQueue.poll(100, ms);
}
}
}
if the timeout is triggered on trackEvent(A) the UI producer not waiting for long time but Does the event "A" missed ?
you could try SEDA approach to this problem with queuing and using an implementation like Blocking queue
in your case, the producer insert event in the queue by using 'offer' and the consumer take them by using 'poll'. (use the Timeout on those method to exit nicely the producer/consumer when the user quit the application)
note that there is a few things to get right on the Threading side when using this approach.
here's an example of the concept from the android developer documentation.
I want to implement a variety of of a publisher/subscriber pattern using Java and currently running out of ideas.
There is 1 publisher and N subscribers, the publisher publish objects then each subscriber need to process the each of the objects once and only once in the correct order. The publisher and each subscriber run in their own thread.
In my original implementation, each subscriber has its own blocking queue, and the publisher put objects into each of the subscriber's queue. This works ok but the publisher will be blocked if any of the subscriber's queue is full. This leads to degration of performance as each subscriber takes different time in processing the object.
Then in another implementation, the publisher hold the object in its own queue. Along with the object, an AtomicInteger counter is associated with it with the number of subscribers out there. Each subscriber then peek the queue and decrease the counter, and remove it from the queue when the counter reach zero.
In this way the publisher is free from blocking but now the subscriber will need to wait for each other to process the object, removing the object from the queue, before the next object can be peeked.
Is there any better way to do this? I assume this should be a quite common pattern.
Your "many queues" implementation is the way to go. I don't think you need to necessarily be concerned with one full queue blocking the producer, because the overall time to completion won't be affected. Let's say you have three consumers, two consume at a rate of 1 per second and the third consumes at a rate of 1 per five seconds, meanwhile the producer produces at a rate of 1 per two seconds. Eventually the third queue will fill up, and so the producer will block on it and will also stop putting items in the first and second queues. There are ways around this, but they're not going to change the fact that the third consumer will always be the bottleneck. If you're producing/consuming 100 items, then this will take at least 500 seconds because of the third consumer (5 seconds times 100 items), and this will be the case even if the first and second consumers finish after 200 seconds (because you've done something clever to allow the producer to continue to fill their queues even after the third queue is full) or if they finish after 500 seconds (because the producer blocked on the third queue).
Definately
each subscriber has its own blocking queue, and the publisher put objects into each of the subscriber's queue.`
this is the way to go.
you can use threaded approach to put it in queue... so if one queue is full publisher will not wait..
for example.
s1 s2 s3 are subscribers and addToQueue is method in each subscriber which adds to corrosponding queue.
The addQueue Method is which waits till queue is non empty .. so call to addQueue will be a blocking call ideally synchronised code...
Then in publisher you can do something similar to below code
NOTE: code might not be in working condition as it is.. but should give you idea.
List<subscriber> slist;// Assume its initialised
public void publish(final String message){
for (final subscriber s: slist){
Thread t=new Thread(new Runnable(){
public void run(){
s.addToQueue(message);
}
});
t.start();
}
}
There is 1 publisher and N subscribers, the publisher publish objects then each subscriber need to process the each of the objects once and only once in the correct order. The publisher and each subscriber run in their own thread.
I would change this architecture. I initially considered the queue per subscriber but I don't like that mechanism. For example, if the first subscriber takes longer to run, all of the jobs will end up in that queue and you will only be doing 1 thread of work.
Since you have to run the subscribers in order, I'd have a pool of threads which run each message through all of the subscribers. The calls to the subscribers will need to be reentrant which may not be possible.
So you would have a pool of 10 threads (let's say) and each one dequeues from the publisher's queue, and does something like the following:
public void run() {
while (!shutdown && !Thread.currentThread().isInterrupted()) {
Article article = publisherQueue.take();
for (Subscriber subscriber : subscriberList) {
subscriber.process(article);
}
}
}
I have the following problem, and I am not sure how to design parts of the solution:
I have a large text file that I read line by line.
I need to process each line and update a HashMap.
AFAIK I need one producer thread to read the lines from the file, and dispatch the lines to a pool of consumer threads. The consumer threads should update the ConcurrentHashMap and then get new lines.
My questions are:
How can the consumer threads access the ConcurrentHashMap?
If I use a fixed thread pool, does the producer need to add the line to a queue first, or can it simply submit or execute a new consumer?
EDIT:
Zim-Zam is correct; I want the consumers to dump their results into the ConcurrentHashMap when they finish.
I create the ConcurrentHashMap in the main thread, and pass references to it to the Consumers in their constructors. The Consumers should either add or increment an AtomicInteger in their run methods. How can I tell in the main thread when all of the lines are read and the consumers are finished?
Thanks again.
You can either have all of the consumers share the same queue that the producer adds to, or else you can give each consumer its own queue that the producer accesses via a circular linked list or a similar data structure so that each consumer's queue receives more or less the same amount of data (e.g. if you have 3 consumers, then the producer would add data to queue1, then queue2, then queue3, then queue1, etc).
You can give each consumer a reference to the same ConcurrentHashMap (e.g. in the consumer's constructor), or else you can make the ConcurrentHashMap accessible via a static getter method.
I think you don't really need to use producer consumer queue in the way you suggested.
Simply have the main queue reading the file, and for each line you read, create a corresponding Runnable object (treat it as a command) and put it to the thread pool executor. The content of the Runnable object is simply the logic of handle that line and putting result to the concurrentHashMap
The ThreadPoolExecutor can be created with a bounded or unbounded blocking queue, depends on the behavior you want.
In pseudo code it is something like this:
class LineHandler implements Runnable {
String line;
ConcurrentHashMap resultMap;
public LineHandler(String line, ConcurrentHashMap resultMap) {
this.line = line;
this.resultMap = resultMap;
}
#Override
public void run() {
// work on line
// update resultMap
}
}
// logic in your file reader thread, supposed to be in a loop:
while (moreLinesInFile()) {
String line = readFromFile();
threadPoolExecutor.submit(new LineHandler(line, concurrentHashMap));
}
threadPoolExecutor.shutdown();
Use a CountDownLatch.
// in main thread
// assume consumers are in some kind of container
List<MyConsumer> consumers...
CountDownLatch latch = new CountDownLatch( consumers.size() );
for( MyConsumer c : consumers ) {
c.setLatch( latch );
c.start(); // starts asychronous, or submit to executor, whatever you're doing
}
// block main thread, optionally timing out
latch.await();
// Then in consumer when it's done it's work:
latch.countDown();
I would suggest you use a BlockingQueue to store the to be processed lines.
After the main thread finished parsing the file, the main thread puts a poison object as the last object into the queue and waits with awaitTermination(...) for the consumers to finish.
The poison object is handled in a special way in a consumer thread. The consumer thread that processes the posion object attemts to shutdown() the ExecutorService, while the main thread is waiting.
As for the result of the consumers just add them to some threadsafe container. The producer/consumer problem is handled by the Queue: poll(...), put(...).
Hope i could help
I have a while loop that checks if an arraylist containing commands for the program to execute is empty. Obviously it does things if not empty, but if it is right now I just have a Thread.sleep(1000) for the else. That leaves anything that interacts with it rather sluggish. Is there any way to get the thread it runs on to block until a new command is added? (It runs in it's own thread so that seems to be the best solution to me) Or is there a better solution to this?
You can use wait() and notify() to have the threads that add something to the list inform the consumer thread that there is something to be read. However, this requires proper synchronization, etc..
But a better way to solve your problem is to use a BlockingQueue instead. By definition, they are synchronized classes and the dequeuing will block appropriately and wakeup when stuff is added. The LinkedBlockingQueue is a good class to use if you want your queue to not be limited. The ArrayBlockingQueue can be used when you want a limited number of items to be stored in the queue (or LinkedBlockingQueue with an integer passed to the constructor). If a limited queue then queue.add(...) would block if the queue was full.
BlockingQueue<Message> queue = new LinkedBlockingQueue<Messsage>();
...
// producer thread(s) add a message to the queue
queue.add(message);
...
// consumer(s) wait for a message to be added to the queue and then removes it
Message message = queue.take();
...
// you can also wait for certain amount of time, returns null on timeout
Message message = queue.poll(10, TimeUnit.MINUTES);
Use a BlockingQueue<E> for your commands.
There's a very good example of how to use it in the link above.
A better solution is to use an ExecutorService. This combines a queue and a pool of threads.
// or use a thread pool with multiple threads.
ExecutorService executor = Executors.newSingleThreadExecutor();
// call as often as you like.
executor.submit(new Runnable() {
#Override
public void run() {
process(string);
}
});
// when finished
executor.shutdown();
n threads produce to a BlockingQueue.
When the queue is full, the consumer drains the queue and does some processing.
How should I decide between the following 2 choices of implementation?
Choice A :
The consumer regularly polls the queue to check if it is full, all writers waiting (it is a blocking queue after all : ).
Choice B :
I implement my own queue with a synchronized "put" method. Before putting the provided element, I test if the queue is not nearly full (full minus 1 element). I then put the element and notify my consumer (which was waiting).
The first solution is the easiest but does polling ; which annoys me.
The second solution is in my opinion more error prone and more requires more coding.
I would suggest to write your proxy queue which would wrap a queue instance internally along with an Exchanger instance. Your proxy methods delegate calls to your internal queue. Check if the internal queue is full when you add and when it is full, exchange the internal queue with the consumer thread. The consumer thread will exchange an empty queue in return for the filled queue. Your proxy queue will continue filling the empty queue while the consumer can keep processing the filled queue. Both activities can run in parallel. They can exchange again when both parties are ready.
class MyQueue implements BlockingQueue{
Queue internalQueue = ...
Exchanger<Queue> exchanger;
MyQueue(Exchanger<BlockingQueue> ex){
this.exchanger = ex;
}
.
.
.
boolean add (E e) {
try{
internalQueue.add(e);
}catch(IllegalStateException ise){
internalQueue = exchanger.exchange(internalQueue);
}
internalQueue.add(e);
}
}
class Consumer implements Runnable {
public void run() {
Queue currentQueue = new empty queue;
while (...){
Object o = currentQueue.remove();
if (o == null){
currentQueue = exchanger.exchange(currentQueue);
continue;
}
//cast and process the element
}
}
}
The second solution is obviously better. And it is not so complicated. You can inherit or wrap any other BlockingQueue and override its method offer() as following: call the "real" offer(). If it returns true, exit. Otherwise trigger the working thread to work and immediately call offer() with timeout.
Here is the almost pseudo code:
public boolean offer(E e) {
if (queue.offer(e)) {
return true;
}
boolean result = queue.offer(e, timeout, unit); // e.g. 20 sec. - enough for worker to dequeue at least one task from the queue, so the place will be available.
worker.doYouJob();
return result; }
I don't know is there such implementation of queue you need: consumer are wait while queue become full and only when it full drain and start processing.
You queue should be blocked for consumers until it become full. Think you need to override drain() method to make it wait while queue become full. Than your consumers just call and wait for drain method. No notification from producer to consumer is needed.
Use an observer pattern. Have your consumers register with the queue notifier. When a producer does a put the queue would then decide whether to notify any listeners.
I used the CountdownLatch which is simple and works great.
Thanks for the other ideas :)