why all producer threads also exit when comsumer threads all exit - java

I am running the below code, and I have one question:
why do all producer threads also exit when the consumer threads all exit.
Here is the code:
public class NumbersConsumer implements Runnable {
private final BlockingQueue<Integer> queue;
private final int poisonPill;
NumbersConsumer(BlockingQueue<Integer> queue, int poisonPill) {
this.queue = queue;
this.poisonPill = poisonPill;
}
public void run() {
try {
while (true) {
Integer number = queue.take();
if (number.equals(poisonPill)) {
return;
}
String result = number.toString();
System.out.println(Thread.currentThread().getName() + " result: " + result);
}
} catch (InterruptedException e) {
System.out.println(e.getStackTrace());
Thread.currentThread().interrupt();
}
}
}
Producer:
public class NumbersProducer implements Runnable {
private final BlockingQueue<Integer> numbersQueue;
private final int poisonPill;
private final int poisonPillPerProducer;
NumbersProducer(BlockingQueue<Integer> numbersQueue, int poisonPill, int poisonPillPerProducer) {
this.numbersQueue = numbersQueue;
this.poisonPill = poisonPill;
this.poisonPillPerProducer = poisonPillPerProducer;
}
public void run() {
try {
generateNumbers();
} catch (InterruptedException e) {
System.out.println(e.getStackTrace());
Thread.currentThread()
.interrupt();
}
}
private void generateNumbers() throws InterruptedException {
for (int i = 0; i < 100; i++) {
numbersQueue.put(ThreadLocalRandom.current()
.nextInt(100));
}
for (int j = 0; j < poisonPillPerProducer; j++) {
numbersQueue.put(poisonPill);
}
}
}
Tester:
public class BlockingQueueUsage {
public static void main(String[] args) {
int BOUND = 10;
int N_PRODUCERS = 4;
int N_CONSUMERS = Runtime.getRuntime().availableProcessors();
int poisonPill = Integer.MAX_VALUE;
int poisonPillPerProducer =N_CONSUMERS / N_PRODUCERS ;
System.out.printf("poisonPillPerProducer:%s,N_CONSUMERS:%s %n",poisonPillPerProducer,N_CONSUMERS);
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(BOUND);
for (int i = 0; i < N_PRODUCERS; i++) {
new Thread(new NumbersProducer(queue, poisonPill, poisonPillPerProducer),"Producer"+i).start();
}
for (int j = 0; j < N_CONSUMERS; j++) {
new Thread(new NumbersConsumer(queue, poisonPill),"comsumer"+j).start();
}
}
}

Simple: your producers are missing a loop.
The produces do nothing but produce some numbers, and that poison pill that will end the consumers.
The consumers on the other hand, would be consuming forever ... until that pill comes in.
In other words: your producers "end", because they aren't designed to stay alive.

Related

Java - How to detect deadlocks and recovery from this?

Right now I write a Java program that has as purpose detect deadlocks and recovery from this situation. The program input is two numbers, N = Number of types of resources and M = Number of process.
I wanted to do something like this:
private static void test2() {
final ReentrantLock lock1 = new ReentrantLock();
final ReentrantLock lock2 = new ReentrantLock();
Thread thread1 = new Thread(new Runnable() {
#Override public void run() {
try {
lock1.lock();
System.out.println("Thread1 acquired lock1");
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException ignore) {}
lock2.lock();
System.out.println("Thread1 acquired lock2");
}
finally {
lock2.unlock();
lock1.unlock();
}
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable() {
#Override public void run() {
try {
lock2.lock();
System.out.println("Thread2 acquired lock2");
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException ignore) {}
lock1.lock();
System.out.println("Thread2 acquired lock1");
}
finally {
lock1.unlock();
lock2.unlock();
}
}
});
thread2.start();
// Wait a little for threads to deadlock.
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException ignore) {}
detectDeadlock();
}
But instead of 2, N locks and I have several problems for doing this. Here my code with my attempt:
class Main {
private static int MAX_AVAILABLE = 10;
private static int IDLE = 1000;
public static void main(String[] args) throws java.lang.Exception{
int n, m; //number of resources and process, respectively
ReentrantLock[] resources; // Locks for resources
int[] available; // Number of instances per resource
Process[] processes; // Processes array
DeadlockDetector supervisor; // Deadlock detaction class
n = Integer.valueOf(args[0]);
m = Integer.valueOf(args[1]);
resources = new ReentrantLock[n];
available = new int[n];
processes = new Process[m];
supervisor = new DeadlockDetector();
// Create resources array
for(int i=0; i<n; ++i){
available[i] = (int)(Math.floor(Math.random()*MAX_AVAILABLE + 1));
resources[i] = new ReentrantLock();
System.out.println("R"+String.valueOf(i+1)+"-> instances: "+String.valueOf(available[i]));
}
// Creating processes
for(int i=0; i<m; ++i){
processes[i] = new Process(i, resources, available, n);
System.out.println("P"+String.valueOf(i+1)+"-> requested "+Arrays.toString(processes[i].requested));
processes[i].start();
}
//Run deadlock detection
try {
TimeUnit.MILLISECONDS.sleep(IDLE);
}catch (InterruptedException ignore){}
supervisor.start();
}
}
class Process extends Thread{
public int id;
public int total; // Total of resources instances needed for finished the process
public ReentrantLock[] resources;
public int[] requested; // Number of instances needed per resource type
public boolean[] needed; // Boolean indicating whether the process needs at least one instance of the resource i
public int n;
private static int MIN_TIME = 1000;
private static int MAX_TIME = 3000;
public Process(int index, ReentrantLock[] res, int[] available, int n_resources){
id = index;
n = n_resources;
resources = res;
total = 0;
requested = new int[n];
needed = new boolean[n];
for(int i=0; i<n; ++i){
requested[i] = (int)(Math.floor(Math.random()*available[i]));
needed[i] = requested[i] > 0;
total += requested[i];
}
}
#Override
public void run(){
int resourceT = 0;
int timeToSleep;
System.out.println("P"+String.valueOf(id+1)+" begin running");
try{
while(total > 0){
resourceT = (int)(Math.floor(Math.random()*n));
if(requested[resourceT] < 1){
System.out.println("P"+String.valueOf(id+1)+"-> I do not need more R"+String.valueOf(resourceT+1));
continue;
}
System.out.println("P"+String.valueOf(id+1)+"-> I'll take R"+String.valueOf(resourceT+1));
resources[resourceT].lock();
timeToSleep = (int)(Math.floor(Math.random()*(MAX_TIME - MIN_TIME)) + MIN_TIME);
try{
TimeUnit.MILLISECONDS.sleep(timeToSleep);
}catch (InterruptedException ignore){}
--total;
--requested[resourceT];
}
}finally{
for(int i=0; i<n; ++i){
if(needed[i] && resources[i].isHeldByCurrentThread())
resources[i].unlock();
}
}
System.out.println("P"+String.valueOf(id+1)+"-> Im finished");
}
}
class DeadlockDetector extends Thread{
public ThreadMXBean threadBean;
public long[] threadIds;
public DeadlockDetector(){
}
#Override
public void run(){
Boolean good;
this.threadBean = ManagementFactory.getThreadMXBean();
threadIds = threadBean.findDeadlockedThreads();
int deadlockedThreads = threadIds != null? threadIds.length : 0;
if(deadlockedThreads>1){
good = false;
System.out.println("Number of deadlocked threads: " + deadlockedThreads);
//recoverDeadlock();
//break;
}
}
public void recoverDeadlock(){
}
}
Please, could anyone help me fix this detail? Thanks!

Why does not thread join?

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.

Why do I get a deadlock?

I have a multithreading program, which sorts threads in order strs times. Every thread has its own monitor. One monitor of this thread (lock) and another monitor of the following thread (unlock) are passed to the constructor of each thread. First, when each thread starts, it must stop when array[0] != this, but if in I write this in line 13, the deadlock appears. So I use Threads.count, which is incremented every iterations. This way the program works. Could you tell me why this happens?
class Foo extends Thread
{
private Object lock, unlock;
Foo(Object lock, Object unlock)
{
this.lock = lock;
this.unlock = unlock;
}
public void run()
{
synchronized(lock)
{
if(Threads.array[Threads.count] != this) // line 13!!!
{
waiter();
}
for(int i = 0; i < Threads.strs; ++i)
{
if(Threads.array[0] == this)
{
System.out.println(i+1);
}
System.out.print(getName() + ' ');
++Threads.count;
if(Threads.array[Threads.thrs-1] == this)
{
System.out.println();
}
if(unlock != lock)
{
synchronized(unlock)
{
unlock.notify();
}
waiter();
}
}
}
}
void waiter()
{
try
{
lock.wait();
}
catch(InterruptedException e)
{
e.printStackTrace();
System.exit(1);
}
}
}
public class Threads
{
public static Thread array[];
public static Object lock[];
public static int count, strs, thrs;
public static void main(String args[])
{
thrs = 0;
strs = 0;
count = 0;
try
{
assert(args.length == 2);
thrs = Integer.parseInt(args[0]);
strs = Integer.parseInt(args[1]);
assert((thrs > 0) && (strs > 0));
}
catch(NumberFormatException | AssertionError e)
{
System.out.println("Uncorrect enter!");
System.exit(1);
}
lock = new Object[thrs];
array = new Thread[thrs];
for(int i = 0; i < thrs; ++i)
{
lock[i] = new Object();
}
for(int i = 0; i < thrs; ++i)
{
if(i != thrs-1)
{
array[i] = new Foo(lock[i],lock[i+1]);
}else
{
array[i] = new Foo(lock[i],lock[0]);
}
array[i].start();
}
}
}
Line 13 basically says "wait to get notified by a preceding thread, unless I am the first thread". Which makes sense: from what I can tell from the code, you want the threads to do their tasks one by one in the order that you have created the threads (which kind of defeats the purpose of using threads, but that is another story).
Also note that the program will not exit since all threads call waiter() at the end the loop.
So the solution is kind of straightforward: have all threads wait at the beginning of the loop, but after creating all threads, trigger the first thread to start running (which in turn will trigger the other threads to start running). Below a slightly adjusted copy of your code with the two changes I mentioned:
class ThreadsInSequence extends Thread
{
private Object lock, unlock;
ThreadsInSequence(Object lock, Object unlock)
{
this.lock = lock;
this.unlock = unlock;
}
public void run()
{
synchronized(lock)
{
for(int i = 0; i < strs; ++i)
{
waiter();
if(array[0] == this)
{
System.out.println(i+1);
}
System.out.print(getName() + ' ');
++count;
if(array[thrs-1] == this)
{
System.out.println();
}
if(unlock != lock)
{
synchronized(unlock)
{
unlock.notify();
}
}
}
}
}
void waiter()
{
try
{
lock.wait();
}
catch(InterruptedException e)
{
e.printStackTrace();
System.exit(1);
}
}
public static Thread array[];
public static Object locks[];
public static int count, strs, thrs;
public static void main(String args[])
{
thrs = 3;
strs = 6;
count = 0;
locks = new Object[thrs];
array = new Thread[thrs];
for(int i = 0; i < thrs; ++i)
{
locks[i] = new Object();
}
for(int i = 0; i < thrs; ++i)
{
if(i != thrs-1)
{
array[i] = new ThreadsInSequence(locks[i],locks[i+1]);
}else
{
array[i] = new ThreadsInSequence(locks[i],locks[0]);
}
array[i].start();
}
synchronized(locks[0]) {
locks[0].notify();
}
}
}

Program Threads hanging when using a semaphore

I have an issue setting up a critical section with a semaphore between 2 threads. I am using a semaphore to acquire(send) in my Customer thread and release in my teller thread. However when I run my program it is always hanging and I don't know why. I have tried several things and i am not sure what the issue was.
I am trying to use the deposit semaphore to set up a critical section with the customer thread and teller thread.
import java.util.concurrent.Semaphore;
public class Threads {
// private int customerNumber = 0;
private static Semaphore deposit = new Semaphore (0, true);
public static void main(String[] args)
{
final int customerThreads = 5;
final int tellerThreads = 2;
final int loanThreads = 1;
Customer thr[] = new Customer[customerThreads]; // make 5 customer threads
Thread cThread[] = new Thread[customerThreads]; // made 5 threads
for (int i= 0; i < customerThreads; i++)
{
thr[i]= new Customer(i);
cThread[i] = new Thread(thr [i]);
cThread[i].start();
}
for ( int i = 0; i < customerThreads; i++ )
{
try {
cThread[i].join ();
System.out.println("Customer"+i + "joined from main");
}
catch (InterruptedException e)
{
}
}
Teller thr1[] = new Teller[tellerThreads];
Thread tThread[] = new Thread[tellerThreads];
for (int b = 0; b< tellerThreads; b++)
{
thr1[b] = new Teller(b);
tThread[b]= new Thread(thr1 [b]);
tThread[b].start();
}
LoanOfficer thr2[] = new LoanOfficer[loanThreads];
Thread lThread[] = new Thread[loanThreads];
for(int c = 0; c< loanThreads; c++)
{
thr2[c] = new LoanOfficer(c);
lThread[c] = new Thread(thr2 [c]);
lThread[c].start();
}
// TODO code application logic here
}
static class Customer implements Runnable
{
private int customerNumber = 0;
private int balance = 0;
Customer(int cn)
{
this.customerNumber = cn;
balance = 1000;
System.out.println("Customer"+ customerNumber + "created");
}
public void run()
{
try
{
Thread.sleep(200);
deposit.acquire();
}
catch(InterruptedException e)
{
Thread.currentThread().interrupt();
e.printStackTrace();
}
//System.out.println("Customer"+ customerNumber + "created");
// try
}
public void post()
{
}
}
static class Teller implements Runnable
{
private int tellerNumber = 0;
Teller(int tn)
{
this.tellerNumber = tn;
System.out.println("Teller"+ tellerNumber +"created");
}
public void run()
{
deposit.release();
// try
// {
//
// // deposit.release();
//
// Thread.sleep(100);
// // deposit.acquire();
// }
// catch(InterruptedException e)
// {
// deposit.release();
// }
//System.out.println("Teller"+ tellerNumber +"created");
}
public void post()
{
}
}
static class LoanOfficer implements Runnable
{
private int loanNumber = 0;
LoanOfficer(int tn)
{
this.loanNumber = tn;
System.out.println("LoanOfficer"+loanNumber+"created");
}
public void run()
{
//System.out.println("LoanOfficer"+loanNumber+"created");
}
public void post()
{
}
}
}
You instantiate semaphore with no permits as below:
private static Semaphore deposit = new Semaphore (0, true);
Hence when you try to call acquire, you wont get the permit to execute beyond and hence blocks. So try atleast having 1 permit so at a time only 1 thread can execute post you acquire the permit from semaphore. You could increase that later as well.
private static Semaphore deposit = new Semaphore (1, true);
Refer the doc here

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) {
}
}
}
}

Categories

Resources