How to control child-thread lifecycle and synchonize it with main-thread? - java

I am trying to create another thread that processes data while main thread doing some more. Main thread must wait till another thread finishes doStuff with all elements.
And my implementation is pretty straight forward.
Please, take a look at processData and tell me is there some more Java-like way to do it?
I read about Phaser but still can't imagine how to use it or what else can I try?
public class MyClass {
private final NodeQueue queue;
MyClass() {
queue = new NodeQueue();
}
public void processData(Set<String> dataSet) {
// allow transfer
queue.transferEnable()
Thread transfer = new Thread(() -> {
queue.transferData();
})
transfer.start();
// doStuff in another thread
for (String element : dataSet) {
queue.add(element);
// do something more
}
// stop transfer
queue.waitTillEmptyQueue();
queue.transferDisable();
try {
transfer.join();
} catch (...) {
// catch
}
}
public class NodeQueue {
private final ConcurrentLinkedQueue<String> queue;
private boolean transferEnabled;
protected NodeQueue() {
queue = new ConcurrentLinkedQueue<>();
transferEnabled = true;
}
protected void transfer() {
while (!queue.isEmpty()) {
doStuff(queue.poll());
}
}
public void transferData() {
while (tranfserEnabled) {
transfer();
}
}
public synchronized void transferEnable() {
transferEnabled = true;
}
public synchronized void transferDisable() {
transferEnabled = false;
}
public void add(String s) {
queue.add(s);
}
public synchronized void waitTillEmptyQueue() {
while (!queue.isEmpty()) {
if (queue.isEmpty()) {
break;
}
}
}
}
}

Let me copy the Phaser example from my own post
Main thread
// Add producer as a party
Phaser phaser = new Phaser(1);
for (int i=0; i<10000; ++i) {
// Add each task as a party
phaser.register();
queue.put(new Task());
}
// Producer arrived and wait for completion of all tasks
phaser.arriveAndAwaitAdvance();
// At the end, there is only 1 party left which is the producer itself
Consumer
while (true) {
Task task = queue.take();
processTask(task);
// Task completed and remove itself as a party
phaser.arriveAndDeregister();
}

Related

How to synchronize three producers and one consumer threads in java

I have to make three producers and one consumer thread. Producers threads is reading chars from file and using buffer of one char. I made Store like above, now i have to synchronize threads to consumer write whole word and give back control to other producer - patern like this
Producer1->Word1
Producer2->word1
Producer3->word1
Producer1->Word2
Producer2->word2
Producer3->word2
Producer1->Word3
Producer2->word3
Producer3->word3
Store (edited):
public class Store {
public static final char CONSUMER_FREE = '\0';
private volatile char consumer = CONSUMER_FREE;
private final ThreadPoolExecutor executor;
public Store(ThreadPoolExecutor executor) {
this.executor = executor;
}
public synchronized void produce(char c) {
while (isConsumerBussy()) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
consumer = c;
notify(); // single Consumer
}
public synchronized char consume() throws StoreProducersRip {
while (isConsumerFree()) {
try {
wait(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
return consumer;
} finally {
freeConsumer();
notifyAll();
}
}
private void freeConsumer() {
consumer = CONSUMER_FREE;
}
private boolean isConsumerBussy() {
return consumer != CONSUMER_FREE;
}
private boolean isConsumerFree() throws StoreProducersRip {
if (executor.getActiveCount() == 0) throw new StoreProducersRip();
return consumer == CONSUMER_FREE;
}
}
You can use locks for this purpose. Below code demonstrates 3 producer synchronous and 1 consumer async to producers but it'd also be sync to multiple consumers here. Also you should add some logic to consume same amount that produced. If you want to get benefits of multithreading, you should buffer your producer input and create some pipeline before consuming.
public class Executor {
public static void main(String[] args) {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
Store store = new Store(executor);
Runnable word1 = new Runnable() {
#Override
public void run() {
store.producerLock.lock();
store.produce('1');
store.produce('2');
store.produce('3');
store.producerLock.unlock();
}
};
Runnable consume = new Runnable() {
#Override
public void run() {
store.consumerLock.lock();
System.out.print(store.consume());
System.out.print(store.consume());
System.out.print(store.consume());
System.out.println();
store.consumerLock.unlock();
}
};
Future p1 = executor.submit(word1);
Future p2 = executor.submit(word1);
Future p3 = executor.submit(word1);
executor.submit(consume);
executor.submit(consume);
executor.submit(consume);
executor.shutdown();
}
}

Adding and removing element from list concurrently

I want to create two threads that one adds elements into ArrayList (or vector) and the other removes elements from this list concurrently. For example, if thread1 adds 20 elements into the list, then thread2 starts removing at the same time until total elements are removed, but these two threads must be work at the same time.
I wrote a producer (adding to the list) thread. In this thread, when the number of elements added to the list is greater than 5 or any number, so new thread must be started but in here I am stuck. I will mark the point that I was stuck.
public class Test{
public static void main(String[] args) {
Data d = new Data();
Thread t = new Thread(new producer(d));
t.start();
}
}
class producer implements Runnable{
Data d;
Data d2;
Object lck;
public producer(Data dd)
{
d=dd;
}
#Override
public void run()
{
for (int i=0;i<100;++i ) {
synchronized (d){
d.a.add(i);
// if i is greater than 5,
// start consumer thread
// which remove elements from ArrayList.
// but how ??
Thread t = new Thread(new Runnable(){
#Override
public void run()
{
//if(d.a.isEmpty())
//wait the adder thread
}
});
t.start();
}
}
}
}
class Data{
ArrayList<Integer> a; // or vector
public Data()
{
a = new ArrayList<>();
}
}
How can I implement a remover thread that removes all elements in the list with the same time with adder thread and synchronize them?
You can try concurrent package of java .
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArrayList.html
You are using synchronized block in thread which will not help in this case. Method in collection or shared data should be synchronized as it will be accessed by multiple thread
In your code, you are creating 100 consumer thread in producer class within synchronized block. This is not efficient way to utilize parallelism using multi-threading. You are creating one thread for one data to be consumed. Once the data is consumed your thread will be in DEAD state and will not be useful to consume other incoming data, this is wastage of resource as well as requires more time to solve problem.
Take reference of below code to solve your consumer producer problem.
import java.util.*;
class Data {
final List<Integer> a;
public Data() {
a = new ArrayList<>();
}
}
public class Producer implements Runnable {
private final Data data;
public Producer(Data data) {
this.data = data;
}
#Override
public void run() {
for (int i = 0; i < 100; i++) {
synchronized (data) {
data.a.add(i);
}
}
}
}
public class Consumer implements Runnable {
private Data data;
private boolean isThreadEnabled = true;
public Consumer(Data data) {
this.data = data;
}
#Override
public void run() {
while (isThreadEnabled) {
synchronized (data) {
if (!data.a.isEmpty()) {
System.out.println(data.a.remove(0));
}
}
}
}
public void stopConsumer() {
isThreadEnabled = false;
}
}
public class ThreadsMain {
public static void main(String args[]) {
try {
Data data = new Data();
Consumer consumerRunnable = new Consumer(data);
Thread producer = new Thread(new Producer(data));
Thread consumer = new Thread(consumerRunnable);
producer.start();
consumer.start();
producer.join();
try {
//wait for consumer to consume data and then stop the thread
Thread.sleep(1000);
consumerRunnable.stopConsumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

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 override executorService shutdown method

I am creating my own thread pool and future object which can execute callable interface parallel. Executor provides shutdown method to stop all worker threads from running. If i am creating a thread pool like below how should I implement the shutdown method to stop after all threads have finished execution?
My custom thread pool looks like this
class MyThreadPool implements java.util.concurrent.Executor
{
private final java.util.concurrent.BlockingQueue<Callable> queue;
public MyThreadPool(int numThreads) {
queue = new java.util.concurrent.LinkedBlockingQueue<>();
for (int i=0 ; i<numThreads ; i++) {
new Thread(new Runnable(){
#Override
public void run() {
while(true) {
queue.take().call();
}
}
}).start();
}
}
#Override
public <T> Future<T> submit(Callable<T> callable) {
FutureTask<T> future = new FutureTask(callable);
queue.put(future);
return future;
}
public void shutdown(){ }
}
I couldnt think of a way to keep list of thread and then check if they are idle or not?
You definitely should hold references to the threads you're creating. For instance, set up a field threads of type List<Thread> and add the threads to this list from within the constructor.
Afterwards, you could implement shutdown() with the help of Thread#join():
public void shutdown() {
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) { /* NOP */ }
}
}
Don't forget to replace while (true) with an appropriate condition (which you toggle in shutdown()) and consider using BlockingQueue#poll(long, TimeUnit) rather than take().
EDIT: Something like:
public class MyThreadPool implements Executor {
private List<Thread> threads = new ArrayList<>();
private BlockingDeque<Callable> tasks = new LinkedBlockingDeque<>();
private volatile boolean running = true;
public MyThreadPool(int numberOfThreads) {
for (int i = 0; i < numberOfThreads; i++) {
Thread t = new Thread(() -> {
while (running) {
try {
Callable c = tasks.poll(5L, TimeUnit.SECONDS);
if (c != null) {
c.call();
}
} catch (Exception e) { /* NOP */ }
}
});
t.start();
threads.add(t);
}
}
public void shutdown() {
running = false;
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) { /* NOP */ }
}
}
// ...
}

One Producer, multiple Consumers

I have been working on some code, but I need help.
I have created one producer and one consumer, however I need to create multiple consumers who will consume the specific String from the producer e.g. I need a consumer that will consume specifically 'Move Left Hand'.
Contained in the code is the buffer, producer, consumer and the main. I am not sure how to notify the correct consumer and compare the string that needs to be consumed. As it stands I only have one consumer.
public class iRobotBuffer {
private boolean empty = true;
public synchronized String take() {
// Wait until message is
// available.
while (empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = true;
// Notify producer that
// status has changed.
notifyAll();
return message;
}
public synchronized void put(String message) {
// Wait until message has
// been retrieved.
while (!empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = false;
// Store message.
this.message = message;
// Notify consumer that status
// has changed.
notifyAll();
}
}
public class iRobotConsumer implements Runnable {
private iRobotBuffer robotBuffer;
public iRobotConsumer(iRobotBuffer robotBuffer){
this.robotBuffer = robotBuffer;
}
public void run() {
Random random = new Random();
for (String message = robotBuffer.take();
! message.equals("DONE");
message = robotBuffer.take()) {
System.out.format("MESSAGE RECEIVED: %s%n", message);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
}
}
public class iRobotProducer implements Runnable {
private iRobotBuffer robotBuffer;
private int number;
public iRobotProducer(iRobotBuffer robotBuffer)
{
this.robotBuffer = robotBuffer;
//this.number = number;
}
public void run() {
String commandInstructions[] = {
"Move Left Hand",
"Move Right Hand",
"Move Both Hands",
};
int no = commandInstructions.length;
int randomNo;
Random random = new Random();
for (int i = 0;
i < commandInstructions.length;
i++) {
randomNo =(int)(Math.random()*no);
System.out.println(commandInstructions[randomNo]);
robotBuffer.put(commandInstructions[i]);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
robotBuffer.put("DONE");
}
}
public class iRobot
{
public static void main(String[] args)
{
iRobotBuffer robotBuffer = new iRobotBuffer();
(new Thread(new iRobotProducer(robotBuffer))).start();
(new Thread(new iRobotConsumer(robotBuffer))).start();
}//main
}//class
The problem is your iRobotBuffer class. It needs to be a queue to support multiple producer / consumers. I've provided the code for such a queue, but java already has an implementation (BlockingDeque<E>).
public class BlockingQueue<T> {
private final LinkedList<T> innerList = new LinkedList<>();
private boolean isEmpty = true;
public synchronized T take() throws InterruptedException {
while (isEmpty) {
wait();
}
T element = innerList.removeFirst();
isEmpty = innerList.size() == 0;
return element;
}
public synchronized void put(T element) {
isEmpty = false;
innerList.addLast(element);
notify();
}
}
As I understand, you would like 3 consumers, one for each move instruction.
You can use an ArrayBlockingQueue from the java.util.concurrent package, in place of the iRobotBuffer class. By the way, you can have a look at the other concurrent collections provided - one may sweet you better.
Then for the consumer, you can peek() at what is in the queue and test if it matches the requirements and then poll().

Categories