ExecutorService doens't work - java

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.

Related

Syncrhonization across two queues and threads

I have two concurrent threads (producer and consumer), and two queues (pending and execution).
This is a sample flow for producer:
"1" - If not duplicate (does not exist in any of queues), push task T1
"3" - If not duplicate (does not exist in any of queues), push task T1
And this is a sample flow for consumer:
"2" - Poll data from "pending" queue
"4" - If found something, push it into "execution" queue and run it in a separate thread.
Notice the numbering above:
If between steps 2 and 4, step 3 happens, it can insert a duplicate because the data is still in-memory and is not pushed into "execution" queue yet.
How can I prevent this? I can not put a lock on both queues because then the "consumer" thread will always keep the lock (it is an always running thread polling for data).
P.S.
This is how my consumer looks like:
while ( true ) {
var nextTask = pending.poll(100, MILLISECOND); //STEP 2
if ( nextTask != null ) {
executeQueue.add(nextTask); //STEP 4
executeInParallel(nextTask);
}
}
This might not be a direct answer to your question. But if you are looking for a solution to queue tasks to process them with a number of threads you should have a look at the Executors from Java.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class JobQueue {
public static void main(String[] args) {
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
executorService.submit(() -> {
// do someting
return "result";
});
}
}
Update: check queue:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class JobQueue {
public static void main(String[] args) {
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
Runnable task = () -> {
// do someting
};
BlockingQueue<Runnable> queue = executorService.getQueue();
if(!queue.contains(task)) {
executorService.submit(task);
}
}
}
You can synchromize on an Object uning wait() and notify()
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
public class JobQueue {
private static final Object syncMon = new Object();
private static final Queue<Object> pending = new ArrayDeque<>();
private static final Set<Object> executing = new HashSet<>();
public void produce(Object o) {
synchronized (syncMon) {
if(pending.contains(o) || executing.contains(o))
return;
pending.add(o);
syncMon.notifyAll();
}
}
public Object consume() throws InterruptedException {
synchronized (syncMon) {
if(pending.isEmpty())
syncMon.wait();
Object task = pending.poll();
if(task != null) {
executing.add(task);
}
return task;
}
}
public void complete(Object task) {
synchronized (syncMon) {
executing.remove(task);
}
}
}
The syncMon object is not necesarry. You could also use wait() and notify() on the Queue directly.
like pending.notifyAll();
To explain this a litte: If you invoke wait() in a synchronized block the lock is released. So the producer can enter the synchronized while the consumer is waiting. If you call notify() or notifyAll() the waiting thread wakes up and takes the lock back, once the producer has exited the synchronized block.
Update 1: add execution set.

Producer Consumer Code Issue (seems Notify method does not release the lock inside loop)

I am trying to implement a producer consumer using wait and notify method. Producer thread that will put some value in the common container that is an array list. Now in the beginning if the Consumer thread got the lock on the list it will check the size of the list and if the size is 0 in that case it will goes into the waiting state. Now the Producer thread will put the first value inside the loop and calls the Notify method so now the Consumer thread should get the notification and consume the value. Again the producer thread should resume and starts the next iteration of the for loop but it is not happening. For loop inside the Producer gets executed first and then consumer code is running.
Please guide me what I am missing I have searched over the web a lot but finding more complex implementations.
Producer.java
package com.multithreading;
import java.util.List;
public class Producer implements Runnable {
public List<Integer> commonObject;
Producer(List<Integer> commonObject) {
this.commonObject = commonObject;
}
#Override
public void run() {
synchronized (commonObject) {
System.out.println("First Thread got the lock");
for (int i = 0; i < 500; i++) {
System.out.println("First Thread producing value");
commonObject.add(i);
System.out.println("First Thread notified");
commonObject.notifyAll();
}
}
}
}
Consumer.java
package com.multithreading;
import java.util.List;
public class Consumer implements Runnable {
public List<Integer> commonObject;
Consumer(List<Integer> commonObject) {
this.commonObject = commonObject;
}
#Override
public void run() {
synchronized (commonObject) {
System.out.println("Second Thread got the lock");
if (commonObject.size() == 0) {
try {
System.out.println("Second Thread going into Waiting state");
commonObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("Second Thread Consuming Value");
for (int i : commonObject) {
System.out.println(i);
}
}
}
}
}
ProducerConsumer.java
package com.multithreading;
import java.util.ArrayList;
import java.util.List;
public class ProducerConsumer {
public static void main(String [] arg){
List<Integer> sharedObject=new ArrayList<Integer>();
Producer producer=new Producer(sharedObject);
Consumer consumer=new Consumer(sharedObject);
Thread t1= new Thread(producer);
Thread t2= new Thread(consumer);
t1.start();
t2.start();
}
}

How to achieve semaphore concept in Java Multithreading? Producer Consumer

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!

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