Accessing result of another Thread that's running a loop - java

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.

Related

Multi-threading with random thread

I try to realize Producer-Consumer pattern with several producers and consumers.
I try to make
CompletableFuture future = CompletableFuture.runAsync(() -> producer.run(), producerService)
.thenRunAsync(() -> consumer.run(), consumerService);
where producer.run() do something and return String but it is not necessary and consumer.run() do something like this
while (!queue.isEmpty()) {
try {
message = queue.poll();
if (message == null || !message.equals(thread)) {
queue.offer(message);
Thread.sleep(1000);
continue;
}
doWork(message);
} catch (InterruptedException e) {
e.printStackTrace();
My Thread has name equals the number of that like 1 or 2, or 3 if there are 3 Threads in consumerService.
message is a random number which I get with
String.valueOf(1 + new Random().nextInt(2)) for 2 Threads as I suppose.
So, my question is
What should I do instead of thenRunAsync() or something else that my consumer can be possible to change Thread to take message from the queue?
It needs to producer generates a list of numbers like 1,2,1,1,2,1,1,1 and Consumer with Thread which has name 1 get from the queue messages with number equals 1 but Thread with name 2 get with number equals 2.
I can't do every message and after that do CompletableFuture.allOf() because, if I'd have about 1_000_000 tasks, I'd have to wait while it generates and after that, I'd be able to call my consumers
CompletableFuture.run* methods are used to run multiple short-living tasks using a thread pool. Your tasks are not short-living, they are looping over queue and handle multiple values. As a result, they occupy threads from the thread pool, and the size of the thread pool decreases, which may lead to a thread starvation (a kind of dead lock).
So you should not use CompletableFuture.run* methods. Use explicit thread creation instead.
Then, make sure that producer puts messages into queue with queue.put() or queue.offer(), and consumer pulls messages with queue.get() or queue.poll(). In your code, consumer both puts and pulls messages, and producer does not interact with the queue at all.
I realized it like
class Stater {
public static boolean STOP = false;
private Producer producer;
private Consumer consumer;
private ExecutorService producerService= Executors.newFixedThreadPool(PRODUCER_NUMBER, taxiFactory);
private ExecutorService consumerService= Executors.newFixedThreadPool(CONSUMER_NUMBER, clientFactory);
private void working() {
for (int i = 0; i < PRODUCER_NUMBER; i++) {
producerService.execute(() -> producer.get());
consumerService.execute(() -> consumer.run());
}
Starter.STOP = true;
producerService.shutdown();
consumerService.shutdown();
}
}
class Common {
private Queue<Message> emergencyQueue;
private BlockingQueue<Message> blockingQueue;
public void insertOrder(Message message) {
if (!blockingQueue.offer(message)) {
emergencyQueue.add(message);
}
}
public Message getOrder() {
if (emergencyQueue.isEmpty()) {
if (!blockingQueue.isEmpty()) {
return blockingQueue.poll();
} else {
return null;
}
} else {
return emergencyQueue.poll();
}
}
public boolean shouldStop() {
return blockingQueue.isEmpty() && emergencyQueue.isEmpty() && Starter.STOP;
}
}
class Consumer implements Runnable{
private Common common;
public void run(){
common.insertOrder(new Message());
}
}
class Producer implements Runnable{
private Common common;
public void run(){
while (!common.shouldStop()) {
Message message=common.getOrder();
if (message == null) {
Thread.sleep(new Random().nextInt(TIME_TO_WAIT));
}
}
}
}

asynchronous threads each running an infinite loop

I'm implementing a program which contains different tasks and all have implemented Runnable. e.g. there is a task which works on a database and sends some of the tuples to a synchronized shared memory and subsequently, there is another thread which checks the shared memory and sends messages to a queue. Moreover, these two threads iterate over an infinite while loop.
Already, I have used the fixedThreadPool to execute these threads.
The problem is that sometimes program control remained in the first running thread and the second one never gets the chance to go to its running state.
Here is a similar sample code to mine:
public class A implements Runnable {
#Override
public void run() {
while(true) {
//do something
}
}
}
public class B implements Runnable {
#Override
public void run() {
while(true) {
//do something
}
}
}
public class Driver {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
A a = new A();
executorService.execute(a);
B b = new B();
executorService.execute(b);
}
}
I'd also done something tricky, make the first thread to sleep once for a second after a short period of running. As a result, it makes the second thread to find the chance for running. But is there any well-formed solution to this problem? where is the problem in your opinion?
This is a good example of Producer/Consumer pattern. There are many ways of implementing this. Here's one naive implementation using wait/notify pattern.
public class A implements Runnable {
private Queue<Integer> queue;
private int maxSize;
public A(Queue<Integer> queue, int maxSize) {
super();
this.queue = queue;
this.maxSize = maxSize;
}
#Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.size() == maxSize) {
try {
System.out.println("Queue is full, " + "Producer thread waiting for "
+ "consumer to take something from queue");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
Random random = new Random();
int i = random.nextInt();
System.out.println("Producing value : " + i);
queue.add(i);
queue.notifyAll();
}
}
}
}
public class B implements Runnable {
private Queue<Integer> queue;
public B(Queue<Integer> queue) {
super();
this.queue = queue;
}
#Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
System.out.println("Queue is empty," + "Consumer thread is waiting"
+ " for producer thread to put something in queue");
try {
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("Consuming value : " + queue.remove());
queue.notifyAll();
}
}
}
}
And here's hot we set things up.
public class ProducerConsumerTest {
public static void main(String[] args) {
Queue<Integer> buffer = new LinkedList<>();
int maxSize = 10;
Thread producer = new Thread(new A(buffer, maxSize));
Thread consumer = new Thread(new B(buffer));
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(producer);
executorService.submit(consumer);
}
}
In this case the Queue acts as the shared memory. You may substitute it with any other data structure that suits your needs. The trick here is that you have to coordinate between threads carefully. That's what your implementation above lacks.
I know it may sound radical, but non-framework parts of asynchonous code base should try avoiding while(true) hand-coded loops and instead model it as a (potentially self-rescheduling) callback into an executor
This allows more fair resources utilization and most importantly per-iteration monitoring instrumentation.
When the code is not latency critical (or just while prototyping) the easiest way is to do it with Executors and possibly CompletableFutures.
class Participant implements Runnable {
final Executor context;
#Override
public void run() {
final Item work = workSource.next();
if (workSource.hasNext()) {
context.execute(this::run);
}
}
}

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

Producer-consumers(many). Consumers take and put into the shared queue

I made a producer-consumer program. It's just a program in core java without any GUI(Swing or SWT). It has one producer who put objects into the queue.
Also there is a few consumers who must add some staff(for example String) into Every object in that shared queue. So, every consumer must handle every object in a shared queue.
In this case - every BookShelf must have items from All consumers in "books" ArrayList. consumers.
Question: What condition should I use in consumers to finish their threads correctly?
Here are the code fragments of the program. Maybe I implemented it in wrong way.
Here is an object for the queue:
public class BookShelf {
private int id;
private String name;
private int height;
private int weigh;
List<String> books = Collections.synchronizedList(new ArrayList<String>());
public BookShelf(int id, String name) {
this.id = id;
this.name = name;
}
public void addBook(String book) {
books.add(book);
}
public boolean eq(String book) {
synchronized (books) {
for (String b: books) {
if (b.equalsIgnoreCase(book)) {
return true;
}
}
}
return false;
}
other setters and getters..
}
Here is the producer class:
public class Producer implements Runnable {
private BlockingQueue myQueue;
public Producer(BlockingQueue myQueue) {
this.myQueue = myQueue;
}
public void run() {
for(int i=0; i<7; i++){
try {
System.out.println("Produced: " + i);
BookShelf myBookShelf = new BookShelf(i, "book #" + i);
myQueue.put(myBookShelf);
} catch (InterruptedException ex) {
//Proper handle
}
}
}
}
Here is one of consumers class:
public class Consumer implements Runnable {
private BlockingQueue myQueue;
public Consumer(BlockingQueue myQueue) {
this.myQueue = myQueue; }
public void run() {
while(true){
try {
BookShelf tempBookShelf = (BookShelf) myQueue.take();
//eq() is my method to check if ArraList has a book.
if (tempBookShelf.eq("Abc book")) {
System.out.println("It already has book");
myQueue.put(tempBookShelf);
Thread.sleep(2000);
} else {
tempBookShelf.addBook("Abc book");
myQueue.put(tempBookShelf);
Thread.sleep(2000);
}
} catch (InterruptedException ex) {
//Proper handle
}
}
}
}
Here is main class:
public class ProducerConsumerTest {
public static void main(String[] args) {
BlockingQueue sharedQueue = new LinkedBlockingQueue();
Thread prodThread = new Thread(new Producer(sharedQueue));
Thread consThread = new Thread(new Consumer(sharedQueue));
Thread consThread2 = new Thread(new Consumer2(sharedQueue));
prodThread.start();
consThread.start();
consThread2.start();
}
}
Register each consumer with the producer. Each consumer has its own queue and the producer puts the object into all the queues. Each consumer then process on the same instance of the object.
public interface Consumer{
public void process(BookShelf bs);
}
public class Producer implements Runnable{
private final List<Consumer> consumers = new CopyOnWriteArrayList<Consumer>(); // thread safe but not efficient with lots of changes
public void register(Consumer c){
consumers.add(c); // thread safe
}
public void run(){
for(;;){
BookShelf bs = generateBookShelfByWhateverMeans();
for (Consumer c : consumers){
c.process(bs);
}
}
}
}
public class BookShelfConsumer implements Runnable, Consumer{
private final BlockingQueue<BookShelf> queue = new LinkedTransferQueue<BookShelf>(); // unbounded & thread safe
public void process(BookShelf bs){
queue.offer(bs); // non-blocking
}
public void run(){
for(;;){
BookShelf bs = queue.take(); // blocks until got object or interrupted
// catch InterruptedException
// do whatever this consumer is supposed to do with the object
}
}
}
I would try using SwingWorker instead. It has a done() method that is executed when it's finished. See this page for some code examples.
If it's not Swing you are using, there is a similar function in Swt called Jobs. Check this page for examples. It also has a done() method being executed when the job is done.
Also there is a few(N number) consumers who must add some staff(for example String) into Every object in that shared queue
I assume you mean every consumer must add their thing to every object which ever enters the queue. In that case, this is not a producer-consumer problem, this is more like an observer-observable problem. Basically, when a new BookShelf is created, that is the Observable. All of the Observers should be notified about the BookShelf and given the opportunity to add their own Book.
I recommend using a ConcurrentLinkedQueue in Bookshelf instead of a synchronized list - it's lock free (doesn't need to be synchronized) and will probably be more efficient.
To end your consumers, change their while(true) loops to while(!cancel) loops. Give each consumer a cancel boolean as an instance variable that initializes to false, and give them a cancel() method that sets cancel to true. Call cancel() on your consumers when you're done with them. If you will always be canceling all of your consumers at once (instead of selectively canceling some but not others), then you can use a static cancel instead of an instance cancel.

Best method to get objects from a BlockingQueue in a concurrent program?

What is the best method to get objects out of a BlockingQueue, in a concurrent program, without hitting a race condition? I'm currently doing the following and I'm not convinced it is the best method:
BlockingQueue<Violation> vQueue;
/*
in the constructor I pass in a BlockingQueue object
full of violations that need to be processed - cut out for brevity
*/
Violation v;
while ( ( v = vQueue.poll(500, TimeUnit.MILLISECONDS) ) != null ) {
// do stuff with the violation
}
I have yet to hit a race condition... but, I'm none too sure if this is truly safe.
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
This example was taken from the JDK 1.6 docs of BlockingQueue. So You can see that you are doing it the right way. Here's the quote which tells you that it have to work:
Memory consistency effects: As with
other concurrent collections, actions
in a thread prior to placing an object
into a BlockingQueue happen-before
actions subsequent to the access or
removal of that element from the
BlockingQueue in another thread.

Categories