How to achieve semaphore concept in Java Multithreading? Producer Consumer - java

I've two threads Producer and Consumer. In objective-c language I've used semaphores to block and release thread Consumer.
Note: This is related to Producer-Consumer Problem But not fully. Here Producer will not wait for consumer to consume. But consumer will wait till Producer produces. Here Consumer is not continuously reading. He's reading Only when Producer tells him to read. And reads only some data. And here its not about shared memory kinda.
Thread Consumer{
while(true) {
//Consumer is waiting
dispatch_semaphore_wait(semaphoreVariable, DISPATCH_TIME_FOREVER);
//Copies the data and then goes to wait.
}
}
Thread Producer{
while(true){
//write to buffer
//Continuously writes to buffer. No Waiting.
//After writing Some Blocks asks consumer to consume
dispatch_semaphore_signal(semaPhoreBlock);
}
}
Like this the semaphore is used to continuously block and release Consumer Thread.
How to achieve this kind of mechanism in JAVA? Any kind of help is greatly appreciated.

I would solve this coordination problem with a "barrier".
The consumer won't read continuously. It only reads a batch of work when the producer notifies him to do so (by reseting the barrier).
I added some waiting for the producer too (so the queue won't overflow if the consumer is too slow), but the producer will only wait if after producing a batch of work, there is no consumer ready to consume it.
see below:
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class BarrierExample {
public static final int BATCH_SIZE = 10;
public static void main(String[] args) throws InterruptedException {
BarrierExample barrierExample = new BarrierExample();
barrierExample.doTheWork();
}
private void doTheWork() throws InterruptedException {
Queue<String> queue = new ConcurrentLinkedQueue();
CyclicBarrier barrier = new CyclicBarrier(2);
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new Producer(BATCH_SIZE, queue, barrier));
executorService.submit(new Consumer(BATCH_SIZE, queue, barrier));
Thread.sleep(4000);
System.out.println("main program: trying to shutdown executor service");
executorService.shutdownNow();
executorService.awaitTermination(5, TimeUnit.SECONDS);
}
}
class Producer implements Callable<Void> {
private final int batchSize;
private Queue queue;
private CyclicBarrier barrier;
private Random random = new Random();
public Producer(int batchSize, Queue queue, CyclicBarrier barrier) {
this.batchSize = batchSize;
this.queue = queue;
this.barrier = barrier;
}
#Override
public Void call() {
while (true) {
IntStream.range(1, batchSize).forEach(i -> queue.add(String.valueOf(random.ints(1, 10).findFirst().getAsInt())));
System.out.println("producer: batch size was added to queue.");
while (barrier.getNumberWaiting() < 1) {
try {
System.out.println("producer: nobody is waiting on barrier. going to sleep now");
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (Thread.currentThread().isInterrupted()) {
break;
}
}
System.out.println("producer: consumer was waiting on barrier. reseting the barrier now");
barrier.reset();
if (Thread.currentThread().isInterrupted()) {
System.out.println("producer is ending now!");
break;
}
}
return null;
}
}
class Consumer implements Callable<Void> {
private final int batchSize;
private Queue queue;
private CyclicBarrier barrier;
public Consumer(int batchSize, Queue queue, CyclicBarrier barrier) {
this.batchSize = batchSize;
this.queue = queue;
this.barrier = barrier;
}
#Override
public Void call() {
while (true) {
boolean barrierIsBroken = false;
try {
System.out.println("consumer: waiting on barrier");
barrier.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (BrokenBarrierException e) {
System.out.println("consumer: barrier is broken!!");
barrierIsBroken = true;
}
if (barrierIsBroken) {
System.out.println("consumer: consuming batch");
IntStream.range(1, batchSize).forEach(i -> System.out.println(queue.remove()));
System.out.println("consumer: queue size:" + queue.size());
}
try {
System.out.println("consumer: going to sleep");
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (Thread.currentThread().isInterrupted()) {
System.out.println("consumer is ending now!");
break;
}
}
return null;
}
}

The Java solution is: don't go for "low level" concepts such a using/implemeenting semaphores.
Instead, use one of the many abstractions that the Java platform is offering, for example the LinkedBlockingQueue.
It is pretty simple: when you got two threads, one thread pushes content into the queue; and the the other reader thread uses the take() method in order to fetch content.
Where: take() blocks! Therefore you don't need to worry at all about sending signals "manually". One thread writes, the reader sits and waits until content becomes available. Meaning: you do not need to tell the reader explicitly "start reading" - that happens implicitly, under the covers.
In that sense: the real answer is to study the offerings that Java has to make, instead of trying to build abstractions yourself. A good starting point are the Oracle tutorials on concurrency. Don't assume that your solution from language A must "work" the same way in another language. In Java, the writer does not need to signal the reader when using a BlockingQueue. So don't make your life more complicated by enforcing a concept that comes from another language!

Related

Accessing result of another Thread that's running a loop

Thread A is a loop that performs calculations.
Thread B needs to read result produced by each iteration of loop enclosed in Thread A.
What would be the best approach to achieve this without blocking anything?
You need the Producer-Consumer pattern here. In Java, you can use BlockingQueues to implement it. Here's an example with an ArrayBlockingQueue that is used to deliver Double calculation results from a producer to a consumer:
Producer.java
class Producer implements Runnable {
private final BlockingQueue<Double> queue;
public Producer(BlockingQueue<Double> q) {
queue = q;
}
public void run() {
try {
while (true) {
Double result = calculateResult();
// This call will make the result available to the consumer:
queue.put(result);
}
} catch (InterruptedException ex) {
// Handle thread interruption here
}
}
}
Consumer.java
class Consumer implements Runnable {
private final BlockingQueue<Double> queue;
public Consumer(BlockingQueue<Double> q) {
queue = q;
}
public void run() {
try {
while (true) {
// This call Will wait until the next result is available:
Double result = queue.take();
// Process the result...
}
} catch (InterruptedException ex) {
// Handle thread interruption here
}
}
}
Program.java
class Program {
public static void main() {
BlockingQueue<Double> queue = new ArrayBlockingQueue<>();
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
new Thread(producer).start();
new Thread(consumer).start();
}
}
If you need, you can create several consumers or several producers (or both) that share the same queue. That will allow you to balance the work between more than two threads.
Also have a look at the BlockingQueue's capabilities and on other implementations, there're plenty of them.

ExecutorService doens't work

I have problem using Executorservice
I implemented Consumer-Producer Pattern
Main
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10000);
Thread producer = new Thread(new Producer(queue));
ExecutorService executorService = Executors.newFixedThreadPool(3);
Runnable consumer1 = new Consumer(queue);
Runnable consumer2 = new Consumer(queue);
Runnable consumer3 = new Consumer(queue);
producer.start();
executorService.submit(consumer1);
executorService.submit(consumer2);
executorService.submit(consumer3);
executorService.shutdown();
}
}
Producer
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Producer implements Runnable{
public BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10000);
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
public synchronized void run() {
for (int i=0; i<100; ++i) {
try {
//System.out.println("i = " + i);
queue.put(i);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
Consumer
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Consumer implements Runnable {
public BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10000);
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
public void run() {
while (true) {
try {
//queue.take(); // case 1
System.out.println(Thread.currentThread().getName() + " Consumer : " + queue.take()); // case 2
} catch (InterruptedException e) {
System.out.println(e);
}
if (queue.isEmpty()) {
break;
}
}
}
}
I wonder why (Consumer.java) case 1 is not working,
but case 2 is fine
It print noting and never stopping (This comment isn't good. Ignore it ㅠㅠ)
I just wonder, Why case 1 is not Stop.
Is there something in System.out.println or BlockingQueue?
(Poducer.java also. If i added print i in Producer.java then Throws InterruptedException)
May be I don't know java and thread well.
Please help me ;(
(My English isn't good, Sorry)
The fundamental problem here is that if the queue ever becomes empty just before the queue.take(), the consumer thread will block until something gets added to the queue. Since you do all the adding to the queue prior to starting the consumers, it is a matter of luck whether one of the consumers will get into a blocked state.
It appears that case 2 (with the console output) slows things down enough that no thread gets into this state. In case 1 processing is so fast that at least one thread finds itself blocked. When I ran your code I found thread 3 blocked, meaning that probably threads 1 and 2 consumed all entries in the queue before thread 3 even had a chance to get started.
If your usecase involves the queue being filled first by the Producer and then running the Consumer threads, you should use poll() instead of take() which will let you detect the condition of running out of elements.

Best synchronization strategy to block worker threads when a database is down

Multiple workers are processing from a queue and when a database failure occurs it will contact a supervisor that will then lock all worker threads and poll the database at an interval until it is up and it will then release all the threads so they can continue processing. The worker threads can either advance or wait with the processing and the supervisor thread can lock or unlock.
I was thinking of an interface like this. What synchronization primitives would you use? Actors would be a good solution but i don't have the time for a rewrite.
public interface Latch {
/**
* This method will cause a thread(s) to only advance if the latch is in an open state. If the
* latch is closed the thread(s) will wait until the latch is open before they can advance.
*/
void advanceWhenOpen();
/**
* Close the latch forcing all threads that reaches the latch's advance method to wait until
* its open again.
*/
void close();
/**
* Opens the latch allowing blocked threads to advance.
*/
void open();
boolean isOpen();
}
What you want is not really a "latch" - at least the "Java Concurrency in Practice" book says that "Once the latch reaches the terminal state, it cannot change state again, so it remains open forever."
But you can use CountDownLatch objects in the background - whenever your "Latch" needs to be closed, then you can create a new CountDownLatch object with the count of one and await() on in in your advanceWhenOpen(). I think that from a readability point of view this would be the best solution.
I would use a ReadWriteLock as the synchronization primitive for this purpose. The advantage of a read/write lock as opposed to a simple monitor or mutex is that multiple threads can hold the read lock at any given time. This is advantageous when you have lots of readers (e.g. your thread pool in this case) and only one or few writers (e.g. the thread checking for open/close of the database).
With a single monitor or mutex, your threads will serialize on the one lock, making that section of code contentious.
One option is to proxy the queue to make it pausable when the database is unavailable. Workers can check the paused state of the queue while processing and, if necessary, wait for it to unpause. A basic code-demonstration:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
public class PausableQueue<T> {
LinkedBlockingQueue<T> q = new LinkedBlockingQueue<T>();
AtomicReference<CountDownLatch> pause = new AtomicReference<CountDownLatch>(new CountDownLatch(0));
public T take() throws InterruptedException {
awaitPause();
return q.take();
}
public void awaitPause() throws InterruptedException {
pause.get().await();
}
public void setPaused(boolean paused) {
if (paused) {
// only update if there are no threads waiting on current countdown-latch
if (!isPaused()) {
pause.set(new CountDownLatch(1));
}
} else {
pause.get().countDown();
}
}
public boolean isPaused() {
return (pause.get().getCount() > 0L);
}
/* *** Test the pausable queue *** */
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
try {
testPause(executor);
} catch (Exception e) {
e.printStackTrace();
}
executor.shutdownNow();
}
private static void testPause(ExecutorService executor) throws Exception {
final PausableQueue<Object> q = new PausableQueue<Object>();
for (int i = 0; i < 3; i++) {
q.q.add(new Object());
}
final CountDownLatch tfinished = new CountDownLatch(1);
Runnable taker = new Runnable() {
#Override
public void run() {
println("Taking an object.");
try {
Object o = q.take();
println("Got an object: " + o);
} catch (Exception e) {
e.printStackTrace();
} finally {
tfinished.countDown();
}
}
};
executor.execute(taker);
tfinished.await();
final CountDownLatch tstarted2 = new CountDownLatch(2);
final CountDownLatch tfinished2 = new CountDownLatch(2);
taker = new Runnable() {
#Override
public void run() {
println("Taking an object.");
tstarted2.countDown();
try {
Object o = q.take();
println("Got an object: " + o);
} catch (Exception e) {
e.printStackTrace();
} finally {
tfinished2.countDown();
}
}
};
q.setPaused(true);
println("Queue paused");
executor.execute(taker);
executor.execute(taker);
tstarted2.await();
// Pause to show workers pause too
Thread.sleep(100L);
println("Queue unpausing");
q.setPaused(false);
tfinished2.await();
// "Got an object" should show a delay of at least 100 ms.
}
private static void println(String s) {
System.out.println(System.currentTimeMillis() + " - " + s);
}
}

How to start a remote thread in java?

I have an apllication where there are three folders. I am trying to implement the producer consumer concept using LinkedBlockingQueue.
Folder 1:
Contains a class which has a shared queue
public static BlockingQueue sharedQueue = new LinkedBlockingQueue();
From a method in this class I try to call the Producer thread and the Consumer thread both of which reside in separate files.
Thread updateThread = new Thread(new Producer(sharedQueue));
Thread takeThread = new Thread(new Consumer(sharedQueue));
updateThread.start();
takeThread.start();
Folder 2:Contains the producer thread class as follows:
public class Producer implements Runnable {
private final BlockingQueue Queue;
public Producer(BlockingQueue sharedQueue){
Queue = sharedQueue;
}
public void run()
{
while (Thread.currentThread() != null) {
Random random = new Random();
int pos = random.nextInt(productList.size());
String query = "insert into tab1 values("+pos+")";
Queue.put(query);
}
}
Folder 3: Contains the consumer class as follows:
public class Consumer implements Runnable{
private final BlockingQueue queue;
Collection<String> joblist;
public Consumer (BlockingQueue sharedQueue) {
queue = sharedQueue;
MonitoringForm.txtInforamtion.append("hi"+sharedQueue.size());
joblist = new ArrayList<String>();
}
#Override
public void run() {
while(true){
try {
for(int i = 0; i < queue.size(); i++)
{
joblist.add(queue.take().toString());
MonitoringForm.txtInforamtion.append("What we got "+queue.take().toString());
}
} catch (InterruptedException ex) {
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
}
try {
Thread.sleep(60*1000);
} catch (Exception e) {
}
}
}
}
Can somebody tell me how to make sure that the data added to the shared queue by Producer class can be taken by Consumer class. The consumer consumes the data every minute. Not necessary that data is consumed as soon as it is produced. Calling the Consumer and Producer threads is not working as I have them in separate directories. Do I have to use remote method invocation? Is it possible for threads?
Here's a sample code I wrote which can help you understand the concept:
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* We want a Producer thread to create random values, and the Consumer thread to
* consume it. One caveat is that if the Producer has already created a random
* value, which the Consumer thread hasn't consumed yet, the Producer thread
* blocks or waits. On the flip side, the Consumer thread waits for the Producer
* thread to produce some value if the Producer thread hasn't already.
*
* Write a program to simulate such a situation.
*/
public class ProducerConsumerCommunication
{
private volatile boolean running = true;
private ArrayBlockingQueue<Integer> buffer = new ArrayBlockingQueue<>(1);
private Random random = new Random(System.currentTimeMillis());
private class ProducerTask implements Runnable
{
public void run()
{
while (running)
{
try
{
Thread.sleep(random.nextInt(2000));
Integer value = random.nextInt();
buffer.put(value); // Blocks if buffer is full.
System.out.println("Value Put: " + value);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
private class ConsumerTask implements Runnable
{
public void run()
{
while (running)
{
try
{
Thread.sleep(random.nextInt(2000));
Integer value = buffer.take(); // Blocks if buffer is empty.
System.out.println("Value Taken: " + value);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public ProducerConsumerCommunication()
{
ExecutorService service = Executors.newCachedThreadPool();
service.execute(new ProducerTask());
service.execute(new ConsumerTask());
service.shutdown();
}
public static void main(String[] args)
{
new ProducerConsumerCommunication();
}
}
In the traditional Consumer/Producer concept the Consumer waits on a resource. And whenever the Producer pushes anything on the Queue it notifies the Consumer via notify() / notifyAll()
Producer :
queue.put(query) ;
obj.notifyAll();
Consumer :
while(true)
{
try {
obj.wait();
}catch (InterruptedException e) {
}
// get data from Queue
data = queue.take();
}
Refer to the following link for more information : example
To run the Producer and Consumer in the fashion like when the Producer produces something in the queue he should Notify the Consumer, and when the Consumer consumed from the queue he should notify to the Producer to produce something in the queue,
To implement your problem in that way you have to use
wait and Notify method if you have one producer and one consumer.
and if you have multiple consumer then you have to use NotifyAll method as well of Object Class,
And in your Consumer if you get this line printed to your console "What we got" then you are sure that Consumer has consumed something from the queue

BlockingQueue: how can multiple producers stop a single consumer?

I wrote a producer/consumer based program using Java's BlockingQueue. I'm trying to find a way to stop the consumer if all producers are done. There are multiple producers, but only one consumer.
I found several solutions for the "one producer, many consumers" scenario, e.g. using a "done paket / poison pill" (see this discussion), but my scenario is just the opposite.
Are there any best practice solutions?
The best-practice system is to use a count-down latch. Whether this works for you is more interesting.....
Perhaps each producer should register and deregister with the consumer, and when all producers are deregistered (and the queue is empty) then the consumer can terminate too.
Presumably your producers are working in different threads in the same VM, and that they exit when done. I would make another thread that calls join() on all the producers in a loop, and when it exist that loop (because all the producer threads have ended) it then notifies the consumer that it's time to exit. This has to run in another thread because the join() calls will block. Incidentally, rolfl's suggestion of using a count down latch would have the problem, if I understand it correctly.
Alternately, if the producers are Callables, then the consumer can call isDone() and isCanceled() on their Futures in the loop, which won't bock, so it can be used right in the consumer thread.
You could use something like the following, i use registerProducer() and unregisterProducer() for keeping track of the producers. Another possible solution could make use of WeakReferences.
It's worth to mention that this solution will not consume the events that have already been queued when the consumer is shut down, so some events may be lost when shutting down.
You would have to drain the queue if the consumer gets interrupt and then process them.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class TestConsumerShutdown {
private static interface SomeEvent {
String getName();
}
private static class Consumer implements Runnable {
private final BlockingQueue<SomeEvent> queue = new ArrayBlockingQueue<>(10);
private final ExecutorService consumerExecutor = Executors.newSingleThreadExecutor();
private final AtomicBoolean isRunning = new AtomicBoolean();
private final AtomicInteger numberProducers = new AtomicInteger(0);
public void startConsumer() {
consumerExecutor.execute(this);
}
public void stopConsumer() {
consumerExecutor.shutdownNow();
try {
consumerExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public void registerProducer() {
numberProducers.incrementAndGet();
}
public void unregisterProducer() {
if (numberProducers.decrementAndGet() < 1) {
stopConsumer();
}
}
public void produceEvent(SomeEvent event) throws InterruptedException {
queue.put(event);
}
#Override
public void run() {
if (isRunning.compareAndSet(false, true)) {
try {
while (!Thread.currentThread().isInterrupted()) {
SomeEvent event = queue.take();
System.out.println(event.getName());
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
System.out.println("Consumer stopped.");
isRunning.set(false);
}
}
}
}
public static void main(String[] args) {
final Consumer consumer = new Consumer();
consumer.startConsumer();
final Runnable producerRunnable = new Runnable() {
#Override
public void run() {
final String name = Thread.currentThread().getName();
consumer.registerProducer();
try {
for (int i = 0; i < 10; i++) {
consumer.produceEvent(new SomeEvent() {
#Override
public String getName() {
return name;
}
});
}
System.out.println("Produver " + name + " stopped.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
consumer.unregisterProducer();
}
}
};
List<Thread> producers = new ArrayList<>();
producers.add(new Thread(producerRunnable, "producer-1"));
producers.add(new Thread(producerRunnable, "producer-2"));
producers.add(new Thread(producerRunnable, "producer-3"));
for (Thread t : producers) {
t.start();
}
}
}

Categories