Why does not thread join? - java

I want to measure thread execution
I wrote following code:
public class Task5 {
public static int [] readerThreadCount = {10};
public static int [] writerThreadCount = {1};
public static void main(String[] args) throws InterruptedException {
for (int readCount : readerThreadCount) {
for (int writeCount : writerThreadCount) {
test(readCount, writeCount, new ArrayHolderBySynchronized());
}
}
}
private static void test(int readCount, int writeCount, ArrayHolder arrayHolder) throws InterruptedException {
final List<Thread> threads = new ArrayList<>();
CyclicBarrier cyclicBarrier = new CyclicBarrier(1, new Summarizer(threads, readCount, writeCount));
for (int i = 0; i < readCount; i++) {
threads.add(new Thread(new ArrayReader(arrayHolder, cyclicBarrier)));
}
for (int i = 0; i < writeCount; i++) {
threads.add(new Thread(new ArrayWriter(arrayHolder, cyclicBarrier)));
}
for(Thread thread:threads){
thread.start();
}
}
}
class Summarizer implements Runnable{
List<Thread> threads;
int readCount;
int writeCount;
Summarizer(List<Thread> threads, int readCount, int writeCount) {
this.threads = threads;
this.readCount = readCount;
this.writeCount = writeCount;
}
#Override
public void run() {
long start = System.currentTimeMillis();
System.out.println("All threads started");
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
System.out.println(readCount + "/" + writeCount + (System.currentTimeMillis() - start));
}
}
class ArrayHolderBySynchronized extends ArrayHolder {
#Override
public synchronized int get(int index) {
System.out.println("read");
return arr[index];
}
#Override
public synchronized void write(int index, int value) {
System.out.println("write");
arr[index] = value;
}
}
class ArrayReader implements Runnable {
ArrayHolder arrayHolder;
CyclicBarrier cyclicBarrier;
ArrayReader(ArrayHolder arrayHolder, CyclicBarrier cyclicBarrier) {
this.arrayHolder = arrayHolder;
this.cyclicBarrier = cyclicBarrier;
}
#Override
public void run() {
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (BrokenBarrierException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
arrayHolder.get(new Random().nextInt(ArrayHolder.ARRAY_SIZE));
}
}
class ArrayWriter implements Runnable {
ArrayHolder arrayHolder;
CyclicBarrier cyclicBarrier;
ArrayWriter(ArrayHolder arrayHolder, CyclicBarrier cyclicBarrier) {
this.arrayHolder = arrayHolder;
this.cyclicBarrier = cyclicBarrier;
}
#Override
public void run() {
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (BrokenBarrierException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
arrayHolder.write(new Random().nextInt(ArrayHolder.ARRAY_SIZE), -1);
}
}
abstract class ArrayHolder {
public static int ARRAY_SIZE = 1_000_000;
protected int[] arr = generateArray();
private int[] generateArray() {
int[] arr = new int[ARRAY_SIZE];
for (int i = 0; i < ARRAY_SIZE; i++) {
arr[i] = i + 1;
}
return arr;
}
public abstract int get(int index);
public abstract void write(int index, int value);
}
but in output I see
All threads started
But appication hangs on thread.join.
What do I wrong?

You have a deadlock in your code:
You are submitting the Summarizer instance as barrierAction to the CyclicBarrier. So when barrier trips it has to execute the Summarizer before any thread awaiting on the barrier is allowed to proceed. But the Summarizer performs thread.join() on all threads that awaiting on that CyclicBarrier.
So the CyclicBarrier is waiting for the Summarizer. The Summarizer is waiting for the threads. And threads are waiting for the CyclicBarrier.

Related

Multi threaded java program to print even and odd numbers alternatively

I was asked to write a two-threaded Java program in an interview. In this program one thread should print even numbers and the other thread should print odd numbers alternatively.
Sample output:
Thread1: 1
Thread2: 2
Thread1: 3
Thread2: 4
... and so on
I wrote the following program. One class Task which contains two methods to print even and odd numbers respectively. From main method, I created two threads to call these two methods. The interviewer asked me to improve it further, but I could not think of any improvement. Is there any better way to write the same program?
class Task
{
boolean flag;
public Task(boolean flag)
{
this.flag = flag;
}
public void printEven()
{
for( int i = 2; i <= 10; i+=2 )
{
synchronized (this)
{
try
{
while( !flag )
wait();
System.out.println(i);
flag = false;
notify();
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
public void printOdd()
{
for( int i = 1; i < 10; i+=2 )
{
synchronized (this)
{
try
{
while(flag )
wait();
System.out.println(i);
flag = true;
notify();
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
}
public class App {
public static void main(String [] args)
{
Task t = new Task(false);
Thread t1 = new Thread( new Runnable() {
public void run()
{
t.printOdd();
}
});
Thread t2 = new Thread( new Runnable() {
public void run()
{
t.printEven();
}
});
t1.start();
t2.start();
}
}
I think this should work properly and pretty simple.
package com.simple;
import java.util.concurrent.Semaphore;
/**
* #author Evgeny Zhuravlev
*/
public class ConcurrentPing
{
public static void main(String[] args) throws InterruptedException
{
Semaphore semaphore1 = new Semaphore(0, true);
Semaphore semaphore2 = new Semaphore(0, true);
new Thread(new Task("1", 1, semaphore1, semaphore2)).start();
new Thread(new Task("2", 2, semaphore2, semaphore1)).start();
semaphore1.release();
}
private static class Task implements Runnable
{
private String name;
private long value;
private Semaphore semaphore1;
private Semaphore semaphore2;
public Task(String name, long value, Semaphore semaphore1, Semaphore semaphore2)
{
this.name = name;
this.value = value;
this.semaphore1 = semaphore1;
this.semaphore2 = semaphore2;
}
#Override
public void run()
{
while (true)
{
try
{
semaphore1.acquire();
System.out.println(name + ": " + value);
value += 2;
semaphore2.release();
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
}
}
}
}
Well, there are many alternatives. I would probably use a SynchronousQueue instead (I don't like low-level wait/notify and try to use higher-level concurrency primitives instead). Also printOdd and printEven could be merged into single method and no additional flags are necessary:
public class App {
static class OddEven implements Runnable {
private final SynchronousQueue<Integer> queue = new SynchronousQueue<>();
public void start() throws InterruptedException {
Thread oddThread = new Thread(this);
Thread evenThread = new Thread(this);
oddThread.start();
queue.put(1);
evenThread.start();
}
#Override
public void run() {
try {
while (true) {
int i = queue.take();
System.out.println(i + " (" + Thread.currentThread() + ")");
if (i == 10)
break;
queue.put(++i);
if (i == 10)
break;
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws InterruptedException {
new OddEven().start();
}
}
Is there any better way to write the same program?
Well, the thing is, the only good way to write the program is to use a single thread. If you want a program to do X, Y, and Z in that order, then write a procedure that does X, then Y, then Z. There is no better way than that.
Here's what I would have written after discussing the appropriateness of threads with the interviewer.
import java.util.concurrent.SynchronousQueue;
import java.util.function.Consumer;
public class EvenOdd {
public static void main(String[] args) {
SynchronousQueue<Object> q1 = new SynchronousQueue<>();
SynchronousQueue<Object> q2 = new SynchronousQueue<>();
Consumer<Integer> consumer = (Integer count) -> System.out.println(count);
new Thread(new Counter(q1, q2, 2, 1, consumer)).start();
new Thread(new Counter(q2, q1, 2, 2, consumer)).start();
try {
q1.put(new Object());
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
private static class Counter implements Runnable {
final SynchronousQueue<Object> qin;
final SynchronousQueue<Object> qout;
final int increment;
final Consumer<Integer> consumer;
int count;
Counter(SynchronousQueue<Object> qin, SynchronousQueue<Object> qout,
int increment, int initial_count,
Consumer<Integer> consumer) {
this.qin = qin;
this.qout = qout;
this.increment = increment;
this.count = initial_count;
this.consumer = consumer;
}
public void run() {
try {
while (true) {
Object token = qin.take();
consumer.accept(count);
qout.put(token);
count += increment;
}
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
}
How about a shorter version like this:
public class OddEven implements Runnable {
private static volatile int n = 1;
public static void main(String [] args) {
new Thread(new OddEven()).start();
new Thread(new OddEven()).start();
}
#Override
public void run() {
synchronized (this.getClass()) {
try {
while (n < 10) {
this.getClass().notify();
this.getClass().wait();
System.out.println(Thread.currentThread().getName() + ": " + (n++));
this.getClass().notify();
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
There is a bit of a trick to kick-start the threads properly - thus the need to an extra notify() to start the whole thing (instead of have both processes wait, or required the main Thread to call a notify) and also to handle the possibility that a thread starts, does it's work and calls notify before the second thread has started :)
My initial answer was non-functional. Edited:
package test;
public final class App {
private static volatile int counter = 1;
private static final Object lock = new Object();
public static void main(String... args) {
for (int t = 0; t < 2; ++t) {
final int oddOrEven = t;
new Thread(new Runnable() {
#Override public void run() {
while (counter < 100) {
synchronized (lock) {
if (counter % 2 == oddOrEven) {
System.out.println(counter++);
}
}
}
}
}).start();
}
}
}

Java : synchronizing on custom collection class

I want to have shared collection class which is filled by producer thread and output is shown by consumer thread. It's sometimes working with 0 element of the collection class but never goes further. In Eclipse I observer "DestroyJVM" thread after application freezes.
There is artificial latency on the producer to simulate "slow" producer. I don't have an idea why application is not working in sequence, like
"Producer acquires lock on collection class, adds Integer, consumer waits, producer releases lock, consumer acquires lock, consumer prints, consumer releases lock, producer acquires..." and so on.
Can anyone point out where is the mistake?
Here is my code:
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;
public class SyncOwnCollMain {
public static void main(String[] args) {
SharedIntegers ints = new SharedIntegers();
Producer producer = new Producer();
Consumer consumer = new Consumer();
producer.setInts(ints);
consumer.setInts(ints);
Thread producerThread = new Thread(producer);
producerThread.setName("ProducerThread");
Thread consumerThread = new Thread(consumer);
consumerThread.setName("ConsumerThread");
producerThread.start();
consumerThread.start();
}
}
class SharedIntegers {
private final List<Integer> ints = new ArrayList<Integer>();
private final int max = 100;
public synchronized void addAtPosition(int i, Integer integer) {
ints.add(i, integer);
}
public synchronized Integer getAtPosition(int i) {
return ints.get(i);
}
public synchronized Integer removeAtPosition(int i) {
return ints.remove(i);
}
public synchronized Integer getSize() {
return ints.size();
}
public synchronized boolean isFinished() {
return max < ints.size();
}
}
class Producer implements Runnable {
private SharedIntegers ints;
private int timeout = 100;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ProducerThread");
if (getInts() != null) {
int i = 0;
Integer integer = null;
while (!getInts().isFinished()) {
synchronized (getInts()) {
integer = i * 3;
getInts().addAtPosition(i, integer);
out.print("Producer added new integer = " + integer + " at " + i + " position");
out.println(". Will sleep now for " + timeout + " ms");
try {
Thread.sleep(timeout);
getInts().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
}
}
}
class Consumer implements Runnable {
private SharedIntegers ints;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ConsumerThread");
if (getInts() != null && getInts().getSize() > 0) {
int i = 0;
while (!getInts().isFinished()) {
synchronized (getInts()) {
showAtPosition(i, getInts());
i++;
try {
getInts().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.yield();
}
}
} else {
Thread.yield();
}
}
private void showAtPosition(int position, SharedIntegers ints) {
out.println("sharedInts[" + position + "] -> " + ints.getAtPosition(position));
}
}
EDITED: I managed to rewrite code so that it will work in the desired manner, however, producerThread and consumerThread don't exit gracefully. Any ideas why?
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;
public class SyncOwnCollMain {
public static void main(String[] args) {
out.println("Main application started");
SharedIntegers ints = new SharedIntegers();
Producer producer = new Producer();
Consumer consumer = new Consumer();
producer.setInts(ints);
consumer.setInts(ints);
Thread producerThread = new Thread(producer);
producerThread.setName("ProducerThread");
Thread consumerThread = new Thread(consumer);
consumerThread.setName("ConsumerThread");
consumerThread.start();
try {
Thread.sleep(1000); // simulate that consumerThread is "anxious" to start
} catch (InterruptedException e) {
e.printStackTrace();
}
producerThread.start();
try {
consumerThread.join(); //let consumerThread finish before main()
producerThread.join(); //let producerThread finish before main()
} catch (InterruptedException e) {
e.printStackTrace();
}
out.println("Main application finished");
}
}
class SharedIntegers {
private final List<Integer> ints = new ArrayList<Integer>();
private final int max = 5;
public synchronized void addAtPosition(int i, Integer integer) {
ints.add(i, integer);
}
public synchronized Integer getAtPosition(int i) {
return ints.get(i);
}
public synchronized Integer removeAtPosition(int i) {
return ints.remove(i);
}
public synchronized Integer getSize() {
return ints.size();
}
public synchronized boolean isFinished() {
return max <= ints.size();
}
public synchronized boolean overflow(int i) {
return i >= max;
}
}
class Producer implements Runnable {
private SharedIntegers ints;
private final int timeout = 500;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ProducerThread");
if (getInts() != null) {
int i = 0;
Integer integer = null;
synchronized (getInts()) {
while (!getInts().isFinished()) {
integer = i * 3;
getInts().addAtPosition(i, integer);
out.print("Producer added new integer = " + integer + " at " + i + " position");
out.println(". Will sleep now for " + timeout + " ms");
try {
getInts().notify();
getInts().wait();
Thread.sleep(timeout); // simulate "slow" producer
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
try {
getInts().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
out.println("Finished ProducerThread");
}
}
class Consumer implements Runnable {
private SharedIntegers ints;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ConsumerThread");
if (getInts() != null) {
synchronized (getInts()) {
int i = 0;
while (!getInts().overflow(i)) {
if (getInts().getSize() > 0) {
showAtPosition(i, getInts());
i++;
}
try {
getInts().notify();
getInts().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
out.println("Finished ConsumerThread");
}
private void showAtPosition(int position, SharedIntegers ints) {
out.println("sharedInts[" + position + "] -> " + ints.getAtPosition(position));
}
}
EDIT 2: solution found : needed to notify consumerThread from producerThread that getInts() lock can be re-acquired. The working code with my comments looks like this (added some data modification by consumerThread):
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;
public class SyncOwnCollMain {
public static void main(String[] args) {
out.println("Main application started");
SharedIntegers ints = new SharedIntegers();
Producer producer = new Producer();
Consumer consumer = new Consumer();
producer.setInts(ints);
consumer.setInts(ints);
Thread producerThread = new Thread(producer);
producerThread.setName("ProducerThread");
Thread consumerThread = new Thread(consumer);
consumerThread.setName("ConsumerThread");
consumerThread.start();
try {
Thread.sleep(1000); // simulate that consumerThread is "anxious" to start
} catch (InterruptedException e) {
e.printStackTrace();
}
producerThread.start();
try {
consumerThread.join(); //let consumerThread finish before main()
producerThread.join(); //let producerThread finish before main()
} catch (InterruptedException e) {
e.printStackTrace();
}
out.println("Main application finished"); // here, main() thread has result produced by producerThread and consumerThread
}
}
class SharedIntegers {
private final List<Integer> ints = new ArrayList<Integer>();
private final int max = 5;
public synchronized void addAtPosition(int i, Integer integer) {
ints.add(i, integer);
}
public synchronized Integer getAtPosition(int i) {
return ints.get(i);
}
public synchronized Integer removeAtPosition(int i) {
return ints.remove(i);
}
public synchronized Integer getSize() {
return ints.size();
}
public synchronized boolean isFinished() {
return max <= ints.size();
}
public synchronized boolean overflow(int i) {
return i >= max;
}
}
class Producer implements Runnable {
private SharedIntegers ints;
private final int timeout = 500;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ProducerThread");
if (getInts() != null) {
int i = 0;
Integer integer = null;
synchronized (getInts()) {
while (!getInts().isFinished()) {
integer = i * 3;
getInts().addAtPosition(i, integer);
out.print("Producer added new integer = " + integer + " at " + i + " position");
out.println(". Will sleep now for " + timeout + " ms");
try {
getInts().notifyAll(); // notify all threads (in this case - consumer thread) that getInts() will be available for other threads to sync and other threads are legitimate to compete for locking getInts()
getInts().wait(); // release lock for getInts()
Thread.sleep(timeout); // simulate "slow" producer
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
out.println("Finished ProducerThread while() loop");
getInts().notifyAll(); // after job is done, need to notify consumer thread that it can compete to obtain getInts() lock
}
}
}
}
class Consumer implements Runnable {
private SharedIntegers ints;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ConsumerThread");
if (getInts() != null) {
int i = 0;
synchronized (getInts()) {
while (!getInts().overflow(i)) {
if (getInts().getSize() > 0) {
out.println(showAtPosition(i, getInts()));
increaseAtPosition(i, getInts());
out.println("After consumer increase : " + showAtPosition(i, getInts()));
i++;
}
try {
getInts().notifyAll(); // notify all threads that other threads are legitimate to compete for getInts() lock
getInts().wait(); // release getInts() lock, wait for allowance notification
} catch (InterruptedException e) {
e.printStackTrace();
}
}
out.println("Finished ConsumerThread while() loop");
}
}
}
private String showAtPosition(int position, SharedIntegers ints) {
return "sharedInts[" + position + "] -> " + ints.getAtPosition(position);
}
private void increaseAtPosition(int position, SharedIntegers ints) {
Integer increased = ints.getAtPosition(position)+1;
ints.removeAtPosition(position);
ints.addAtPosition(position, increased);
}
}
Your call to getInts().wait(); causes each Thread to wait forever, since you never call notify() , therefore your application freezes.
See the Javadoc for java.lang.Object.wait() and java.lang.Object.notify()
Inside the Producer, change
getInts().wait()
to
getInts().notify()

How to make sure two threads printing even odd numbers maintain even first then odd order for this implementation?

I have created two runnable jobs: PrintEvenNumbersJob and PrintOddNumbersJob and spawned two threads to execute these jobs. This seems to work perfectly fine! But I smell something suspicious about this implementation. Can I have some comments and advice on this implementation?
The problem that I see with this implementation is that the program terminates only when thread1 gains the lock to the object lock first otherwise it print the odd first even second order and doesn't terminate unless I supply yet another statement "lock.notify" after for statement in PrintEvenNumbersJob (as in this implementation). My question here is how to make sure that thread1 is executed first.
public class PrintEvenNumbersJob implements Runnable {
private Object lock;
public PrintEvenNumbersJob(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 0; i <= 10; i += 2) {
lock.notify();
System.out.println(i);
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify(); // not required if thread1 gains lock first
}
}
}
public class PrintOddNumbersJob implements Runnable {
private Object lock;
public PrintOddNumbersJob(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 1; i < 10; i += 2) {
lock.notify();
System.out.println(i);
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify();
}
}
}
public class EvenOddManager {
public static void main(String[] args) {
Object lock = new Object();
PrintEvenNumbersJob printEvenNumbersJob = new PrintEvenNumbersJob(lock);
PrintOddNumbersJob printOddNumbersJob = new PrintOddNumbersJob(lock);
Thread thread1 = new Thread(printEvenNumbersJob);
Thread thread2 = new Thread(printOddNumbersJob);
thread2.start();
thread1.start();
}
}
Have you try using Semaphores? It's easier because you don't need to worry about the order that wait and notify are called (if you call notify before the wait, it's "lost")
Sample code:
import java.util.concurrent.*;
public class Test {
private final Semaphore oddJobPermits = new Semaphore(0);
private final Semaphore evenJobPermits = new Semaphore(1);
private class EvenJob implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
try {
evenJobPermits.acquire();
System.out.println(i * 2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
oddJobPermits.release();
}
}
}
}
private class OddJob implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
try {
oddJobPermits.acquire();
System.out.println(i * 2 + 1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
evenJobPermits.release();
}
}
}
}
public void run() {
new Thread(new EvenJob()).start();
new Thread(new OddJob()).start();
}
public static void main(String[] args) {
new Test().run();
}
}
I believe you will need a referee:
public class Referee {
private boolean evensTurn = true;
public void waitMyTurn(boolean even) {
synchronized(this) {
while (even != evensTurn) {
try {
wait();
} finally {
}
}
}
}
public void done() {
synchronized(this) {
evensTurn = !evensTurn;
notify();
}
}
}
public class PrintEvenNumbersJob implements Runnable {
private Referee referee;
public PrintEvenNumbersJob(Referee referee) {
this.referee = referee;
}
#Override
public void run() {
for (int i = 0; i <= 10; i += 2) {
referee.waitMyTurn(true);
System.out.println(i);
referee.done();
}
}
}
public class PrintOddNumbersJob implements Runnable {
private Referee referee;
public PrintOddNumbersJob(Referee referee) {
this.referee = referee;
}
#Override
public void run() {
for (int i = 0; i <= 10; i += 2) {
referee.waitMyTurn(false);
System.out.println(i);
referee.done();
}
}
}
I tried and tested this code. It works using Semaphore
public class TestSemaphore
{
public static void main(String[] args)
throws Exception
{
AtomicInteger count = new AtomicInteger();
Semaphore s = new Semaphore(1, true);
Semaphore t = new Semaphore(1, true);
OddNumberThread oThread = new OddNumberThread(count, s, t);
EvenNumberThread eThread = new EvenNumberThread(count, s, t);
eThread.start();
oThread.start();
}
static class EvenNumberThread
extends Thread
{
private AtomicInteger count;
private Semaphore s, t;
public EvenNumberThread(AtomicInteger pCount, Semaphore pS, Semaphore pT)
{
super("Even");
count = pCount;
s = pS;
t = pT;
}
#Override
public void run()
{
// Make this thread wait until even thread starts, Order will be incorrect if removed these lines.
s.acquireUninterruptibly();
while (count.intValue() <= 10)
{
try
{
// Double checking to make it work
s.acquireUninterruptibly();
System.out.println(getName() + " " + count.getAndIncrement());
}
finally
{
t.release();
}
}
}
}
static class OddNumberThread
extends Thread
{
private AtomicInteger count;
private Semaphore s, t;
public OddNumberThread(AtomicInteger pCount, Semaphore pS, Semaphore pT)
{
super("Odd");
count = pCount;
s = pS;
t = pT;
}
#Override
public void run()
{
// Start this thread first and start printing, Order will be incorrect if removed these lines.
t.acquireUninterruptibly();
s.release();
while (count.intValue() <= 10)
{
try
{
t.acquireUninterruptibly();
System.out.println(getName() + " " + count.getAndIncrement());
}
finally
{
s.release();
}
}
}
}
}

Producer Consumer using threads

I’m writing a program that implements the Producer Consumer problem in Java using multithreading concepts. Below are few details how I’m supposed to do it:
1) The main thread should create a buffer with capacity specified as a command line argument. The number of producer and consumer threads are also specified as command line arguments. I’m supposed to assign a unique number to each producer and consumer thread. How do I assign a unique number to producer and consumer threads?
2) The producer thread operates in an infinite loop. It produces a data item (a string) with the following format: <producer number>_<data item number>. For example the 1st data item from thread number 1 will be 1_1 and second data item from thread number 3 will be 3_2. How do create data items in such a format?
3) Then the Producer thread writes an entry into the producer log file (< producer number > “Generated” <data item>). Upon writing the log entry, it attempts to insert into the buffer. If insertion is successful, it creates an entry into the log file (<producer number> <data item> “Insertion successful”). How do I write such a code?
Below is the Java code I wrote.
import java.util.*;
import java.util.logging.*;
public class PC2
{
public static void main(String args[])
{
ArrayList<Integer> queue = new ArrayList<Integer>();
int size = Integer.parseInt(args[2]);
Thread[] prod = new Thread[Integer.parseInt(args[0])];
Thread[] cons = new Thread[Integer.parseInt(args[1])];
for(int i=0; i<prod.length; i++)
{
prod[i] = new Thread(new Producer(queue, size));
prod[i].start();
}
for(int i=0; i<cons.length; i++)
{
cons[i] = new Thread(new Consumer(queue, size));
cons[i].start();
}
}
}
class Producer extends Thread
{
private final ArrayList<Integer> queue;
private final int size;
public Producer(ArrayList<Integer> queue, int size)
{
this.queue = queue;
this.size = size;
}
public void run()
{
while(true){
for(int i=0; i<size; i++)
{
System.out.println("Produced: "+i+" by id " +Thread.currentThread().getId());
try
{
produce(i);
Thread.sleep(3000);
}
catch(Exception e)
{
Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, e);
}
}}
}
public void produce(int i) throws InterruptedException
{
while(queue.size() == size)
{
synchronized(queue)
{
System.out.println("Queue is full "+Thread.currentThread().getName() +" is waiting, size: "+queue.size());
queue.wait();
}
}
synchronized(queue)
{
queue.add(i);
queue.notifyAll();
}
}
}
class Consumer extends Thread
{
private final ArrayList<Integer> queue;
private final int size;
public Consumer(ArrayList<Integer> queue, int size)
{
this.queue = queue;
this.size = size;
}
public void run()
{
while(true)
{
try
{ System.out.println("Consumed: "+consume());
Thread.sleep(1000);
}
catch(Exception e)
{
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, e);
}
}
}
public int consume() throws InterruptedException
{
while(queue.isEmpty())
{
synchronized(queue)
{
System.out.println("Queue is empty "+Thread.currentThread().getName()+" is waiting, size: "+queue.size());
queue.wait();
}
}
synchronized (queue)
{
queue.notifyAll();
System.out.println("Consumed by id "+Thread.currentThread().getId());
return (Integer) queue.remove(0);
}
}
}
How can I carry out the above steps?
I’m supposed to assign a unique number to each producer and consumer
thread. How do I assign a unique number to producer and consumer
threads?
Add an instance (non-static) variable to the Producer/Consumer classes. When you initialize the new Producer/Consumer Objects, pass in the unique number. You can keep track of what number you're on with an int counter in your main class.
2) The producer thread operates in an infinite loop. It produces a
data item (a string) with the following format: < producer number >_<
data item number > . For example the 1st data item from thread number
1 will be 1_1 and second data item from thread number 3 will be 3_2.
How do create data items in such a format?
Use synchronized methods and/or atomic variables. Look into Java Concurrency.
3) Then the Producer thread writes an entry into the producer log file
(< producer number > “Generated” < data item >). Upon writing the log
entry, it attempts to insert into the buffer. If insertion is
successful, it creates an entry into the log file (< producer number >
< data item > “Insertion successful”). How do I write such a code?
My answer is the same as the previous question: read about Java concurrency. Spend an hour reading about synchronization, locks, and atomic variables and I guarantee you will easily write your program.
For producer consumer problem best solution is BlockingQueue. I was testing a few things so designed same kind of program now modified it as per your need.
See if it helps.
import java.util.concurrent.*;
public class ThreadingExample {
public static void main(String args[]){
BlockingQueue<Message> blockingQueue = new ArrayBlockingQueue<Message>(100);
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Producer(blockingQueue));
exec.execute(new Consumer(blockingQueue));
}
}
class Message{
private static int count=0;
int messageId;
Message(){
this.messageId=count++;
System.out.print("message Id"+messageId+" Created ");
}
}
class Producer implements Runnable{
private BlockingQueue<Message> blockingQueue;
Producer(BlockingQueue<Message> blockingQueue){
this.blockingQueue=blockingQueue;
}
#Override
public void run(){
while(!Thread.interrupted()){
System.out.print("Producer Started");
try {
blockingQueue.put(new Message());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Producer Done");
}
}
}
class Consumer implements Runnable{
private BlockingQueue<Message> blockingQueue;
Consumer(BlockingQueue<Message> blockingQueue){
this.blockingQueue=blockingQueue;
}
#Override
public void run(){
while(!Thread.interrupted()){
System.out.print("Concumer Started");
try{
Message message = blockingQueue.take();
System.out.print("message Id"+message.messageId+" Consumed ");
}
catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Concumer Done");
}
}
}
I tried the following which might work for you, except for the buffer condition on 3, which you can add the part of the code by yourself.
Hope this helps.
public class Message {
private String msg;
public Message(String msg) {
super();
this.msg = msg;
}
public String getMsg(){
return msg;
}
}
import java.util.concurrent.BlockingQueue;
public class Producer implements Runnable {
private BlockingQueue<Message> queue;
private boolean run = true;
public Producer(BlockingQueue<Message> queue) {
super();
this.queue = queue;
}
public void setRun(boolean val) {
this.run = val;
}
#Override
public void run() {
int i = 0;
while (run) {
Message msg = new Message(Thread.currentThread().getName() + "_"+ i);
try {
Thread.sleep(i * 100);
queue.put(msg);
System.out.println("Producer: "+Thread.currentThread().getName()+" produced and added to the queue: "+msg.getMsg());
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
if(i==10){
setRun(false);
System.out.println(Thread.currentThread().getName()+" stopped");
}
}
}
}
import java.util.concurrent.BlockingQueue;
public class Consumer implements Runnable{
private BlockingQueue<Message> queue;
private boolean run = true;
public Consumer(BlockingQueue<Message> queue) {
super();
this.queue = queue;
}
public void setRun(boolean val){
this.run = val;
}
#Override
public void run() {
while(run){
try {
Thread.sleep(100);
Message msg = queue.take();
System.out.println("Consumer: "+Thread.currentThread().getName()+" generated/consumed "+msg.getMsg());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProducerConsumerMain {
public static void main(String[] args) {
System.out
.println("please enter the number of producer:consumer:size of the queue in order");
Scanner scan = new Scanner(System.in);
Thread[] prodThreads = new Thread[scan.nextInt()];
Thread[] consThreads = new Thread[scan.nextInt()];
BlockingQueue<Message> queue = new ArrayBlockingQueue<Message>(scan.nextInt());
for (int i = 0; i < prodThreads.length; i++) {
prodThreads[i] = new Thread(new Producer(queue), "" + i);
prodThreads[i].start();
}
for (int i = 0; i < consThreads.length; i++) {
consThreads[i] = new Thread(new Consumer(queue), "" + i);
consThreads[i].start();
}
}
}
Please refer the below code. You can change the constant values based on the command line arguments. I have tested the code, its working as per your requirement.
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumerProblem {
public static int CAPACITY = 10; // At a time maximum of 10 tasks can be
// produced.
public static int PRODUCERS = 2;
public static int CONSUMERS = 4;
public static void main(String args[]) {
Queue<String> mTasks = new LinkedList<String>();
for (int i = 1; i <= PRODUCERS; i++) {
Thread producer = new Thread(new Producer(mTasks));
producer.setName("Producer " + i);
producer.start();
}
for (int i = 1; i <= CONSUMERS; i++) {
Thread consumer = new Thread(new Consumer(mTasks));
consumer.setName("Consumer " + i);
consumer.start();
}
}
}
class Producer implements Runnable {
Queue<String> mSharedTasks;
int taskCount = 1;
public Producer(Queue<String> mSharedTasks) {
super();
this.mSharedTasks = mSharedTasks;
}
#Override
public void run() {
while (true) {
synchronized (mSharedTasks) {
try {
if (mSharedTasks.size() == ProducerConsumerProblem.CAPACITY) {
System.out.println("Producer Waiting!!");
mSharedTasks.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (mSharedTasks.size() != ProducerConsumerProblem.CAPACITY) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
String produceHere = Thread.currentThread().getName()
+ "_Item number_" + taskCount++;
synchronized (mSharedTasks) {
mSharedTasks.add(produceHere);
System.out.println(produceHere);
if (mSharedTasks.size() == 1) {
mSharedTasks.notifyAll(); // Informs consumer that there
// is something to consume.
}
}
}
}
}
}
class Consumer implements Runnable {
Queue<String> mSharedTasks;
public Consumer(Queue<String> mSharedTasks) {
super();
this.mSharedTasks = mSharedTasks;
}
#Override
public void run() {
while (true) {
synchronized (mSharedTasks) {
if (mSharedTasks.isEmpty()) { // Checks whether there is no task
// to consume.
try {
mSharedTasks.wait(); // Waits for producer to produce!
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
while (!mSharedTasks.isEmpty()) { // Consumes till task list is
// empty
try {
// Consumer consumes late hence producer has to wait...!
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (mSharedTasks) {
System.out.println(Thread.currentThread().getName()
+ " consumed " + mSharedTasks.poll());
if (mSharedTasks.size() == ProducerConsumerProblem.CAPACITY - 1)
mSharedTasks.notifyAll();
}
}
}
}
}
public class ProducerConsumerTest {
public static void main(String[] args) {
CubbyHole c = new CubbyHole();
Producer p1 = new Producer(c, 1);
Consumer c1 = new Consumer(c, 1);
p1.start();
c1.start();
}
}
class CubbyHole {
private int contents;
private boolean available = false;
public synchronized int get() {
while (available == false) {
try {
wait();
} catch (InterruptedException e) {
}
}
available = false;
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
wait();
} catch (InterruptedException e) {
}
}
contents = value;
available = true;
notifyAll();
}
}
class Consumer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Consumer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
int value = 0;
for (int i = 0; i < 10; i++) {
value = cubbyhole.get();
System.out.println("Consumer #"
+ this.number
+ " got: " + value);
}
}
}
class Producer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Producer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
for (int i = 0; i < 10; i++) {
cubbyhole.put(i);
System.out.println("Producer #" + this.number
+ " put: " + i);
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
}
}
}
}

Is my producer/consumer solution correct?

I'm trying to learn more about threads and thought that coming up with a solution to the producer/consumer problem would be a good start. One of the constraints I put on the solution was that the consumer does not know ahead of time how much the producer is producing. The code runs as expected and I've run it many many times, but that doesn't mean that it is free of flaws. Are there any problems with this solution?
package Multithreading.ProducerConsumer;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;
public class ProducerConsumer
{
private class Producer implements Runnable
{
#Override
public void run()
{
for(int i = 0; i < 1000; i++)
{
try
{
canProduce.acquire();
mutex.acquire();
queue.add(i);
mutex.release();
canConsume.release();
}
catch (InterruptedException ex)
{
;
}
}
try
{
canConsume.acquire();
isTryingToFinish = true;
canConsume.release();
}
catch (InterruptedException ex)
{
;
}
}
}
private class Consumer implements Runnable
{
#Override
public void run()
{
while(!isDone)
{
try
{
canConsume.acquire();
mutex.acquire();
System.out.println(queue.pop());
if(isTryingToFinish && queue.isEmpty())
{
isDone = true;
}
mutex.release();
canProduce.release();
}
catch (InterruptedException ex)
{
;
}
}
}
}
Semaphore canProduce;
Semaphore canConsume;
Semaphore mutex;
boolean isTryingToFinish = false;
boolean isDone = false;
final static int bufferSize = 100;
LinkedList<Integer> queue;
public ProducerConsumer()
{
queue = new LinkedList<>();
canProduce = new Semaphore(bufferSize);
canConsume = new Semaphore(0);
mutex = new Semaphore(1);
}
public void Go() throws InterruptedException
{
Thread p = new Thread(new Producer());
Thread c = new Thread(new Consumer());
p.start();
c.start();
p.join();
c.join();
System.out.println("Job Complete!");
}
public static void main(String[] args) throws InterruptedException
{
ProducerConsumer p = new ProducerConsumer();
p.Go();
}
}
You could look at MSDN's 'Example 2: Synchronizing two threads: a producer and a consumer'. It's c# but that should not be a problem.

Categories

Resources