Java thread producer and consumer program issue - java

I am trying the Java thread producer and consumer program.
but consumer thread always goes to waiting status .
I unable to debug the issues why consumer thread always goes to waiting status or producer not notify to consumer thread
please help me to fix this . The programs are below.
The communicator class calls the both producer and consumer class
public class Communicator {
Thread t = null;
Thread t1 = null;
public void runThread() {
Producer p = new Producer();
Consumer c = new Consumer(p);
t = new Thread(p);
t1 = new Thread(c);
t.start();
t1.start();
Thread tr = new Thread() {
public void run() {
for (int i = 0; i < 30; i++) {
System.out.println("t::::::::::::: " + t.getState());
System.out.println("t1::::::::::::: " + t1.getState());
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
};
tr.start();
}
public static void main(String[] args) {
Communicator c = new Communicator();
c.runThread();
}
}
This is producer class which append the data in stringbuffer and notify to consumer class
public class Producer extends Thread {
public StringBuffer sb;
public Producer() {
sb = new StringBuffer();
}
public void run() {
synchronized (sb) {
try {
System.out.println("Bala");
sb.append("murugan");
sb.notify();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Below is consumer class code . it wait up to get notifications from producer class.
public class Consumer extends Thread {
public Producer p;
public Consumer(Producer p) {
this.p = p;
}
public void run(){
synchronized (p.sb) {
try {
p.sb.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(p.sb);
}
}
}

There are few problems with your current code in which the Consumer thread always be in waiting state whereas the producer is already terminated.
Also, your StringBuffer object needs to be volatile so that the producer thread writes will be flushed & available to the other thread.
Along with that, I have modified your Producer and Consumer code to make it more realistic (both run in while loop one producing some data and the other receiving the data) as shown below: (I have also added 1 sec sleep to run the things in slower pace so that you can understand the things better):
Consumer class:
public class Producer extends Thread {
public volatile StringBuffer sb;
public Producer() {
sb = new StringBuffer();
sb.append("");
}
public void run() {
synchronized (sb) {
try {
while(true) {
Thread.sleep(1000);
if(sb.toString().equals("")) {
sb.append("murugan");
System.out.println(" producing sb completed *** ");
sb.notify();
} else {
sb.wait();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Consumer class:
public class Consumer extends Thread {
public Producer p;
public Consumer(Producer p) {
this.p = p;
}
public void run(){
synchronized (p.sb) {
try {
while(true) {
Thread.sleep(1000);
if(p.sb.toString().equals("")) {
p.sb.wait();
} else {
String str = p.sb.toString();
System.out.println(" consuming sb completed **** "+str);
p.sb.replace(0, str.length(), "");
p.sb.notify();
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(p.sb);
}
}
}

for your question,"I unable to debug the issues why consumer thread always goes to waiting status or producer not notify to consumer thread".
Actually your consumer is not always in wait status.
You can just put Thread.sleep(1000);before p.sb.wait(); in your Consumer class,then you can see "consumerThread::::::::::::: RUNNABLE" for once.
IMHO,your consumer code runs too fast to get wait status,so you miss the runnable status. You can learn more from other answers.

The Producer is already Terminated, and it already invoked notify() before the Consumer invoke wait().
Since Producer and Consumer extends Thread, update the Communicator class to this:
public class Communicator {
public void runThread() {
final Producer p = new Producer();
final Consumer c = new Consumer(p);
p.start();
c.start();
Thread tr = new Thread() {
public void run() {
for (int i = 0; i < 30; i++) {
System.out.println("t::::::::::::: " + p.getState());
System.out.println("t1::::::::::::: " + c.getState());
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
};
tr.start();
}
public static void main(String[] args) {
Communicator c = new Communicator();
c.runThread();
}
}
If the Producer is not yet Terminated [if (p.getState() != Thread.State.TERMINATED)], that's the only time Consumer will wait:
public class Consumer extends Thread {
public Producer p;
public Consumer(Producer p) {
this.p = p;
}
public void run() {
synchronized (p.sb) {
try {
if (p.getState() != Thread.State.TERMINATED) {
p.sb.wait();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(p.sb);
}
}
}

It´s is not a answer but a suggestion ... You could simplify the whole logic using BlockingQueue to transfer data from Producer(s) to Consumer(s). All waits and notifies would disappear!
Producer(s) send data to be consumed calling BlockingQueue.offer(String)
Consumer(s) wait (blocked) for data calling BlockingQueue.pool();

As per your code, Consumer Thread waits for the Producer to notify about the string appended in the StringBuffer.
If Producer thread gets the chance to acquire the lock on shared StringBuffer object (it enters the synchronized block) then Consumer Thread will go in Blocked state(will not be able to enter the synchronized block) as its also a competitor for the Lock (both compete for acquiring the lock on same shared object).
Producer thread completes its execution, leaves the synchronized block and gets Terminated. Note that the notify code will not have any impact as Consumer thread is not yet waiting on the shared object as it is yet to enter the synchronized block
Consumer thread gets the chance to acquire the lock and enter the synchronized block It waits for some one to give notification on the shared object. But as Producer is already terminated no one gives the notification to Consumer thread and it remains in Waiting state.
Fix : In your case you can simply ensure that Consumer thread is started first and acquires the lock before Producer thread. For this you can have the main thread to sleep for some time after starting the Consumer thread.
t = new Thread(p);
t1 = new Thread(c);
t1.start();
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
t.start();
Key Point : In case you have only 2 threads, one thread should invoke notify and wait. Other thread upon being notified and only the thread in competition for Lock will acquire the lock and do its job. Upon completion of its job it should invoke notify and will wait for the other thread to do job and give notification once done. This way both the threads will get chance to do their jobs one after the other.

Related

Threads producer consumer in java

Below is the consumer producer problem code, but the code is not working as expected. Here the consumer and producer are supposed to be just producing and consuming one object.
public class ProducerConsumer {
private static LinkedList<Integer> linkedList = new LinkedList<>();
public static void main(String a[]) throws InterruptedException {
Thread producer = new Thread(new Runnable() {
#Override
public void run() {
synchronized(this) {
while (linkedList.size() == 1) {
try {
wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produced");
linkedList.add(1);
notify();
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread consume = new Thread(new Runnable() {
#Override
public void run() {
// produce
synchronized(this) {
while (linkedList.isEmpty()) {
try {
wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Consumed");
linkedList.removeFirst();
notify();
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
});
producer.start();
consume.start();
producer.join();
consume.join();
}
}
We get the output as : Produced
And the program hangs.
Please help with possible solutions/ explanations
Use a shared lock. In the posted code each Runnable is using itself as a lock so no actual locking takes place.
When a thread waits, another thread needs to call notify on the same lock in order to wake up the waiting thread. We know from your logging that the Producer thread does its thing, but since the notify acts on a lock that is not the same as the one the Consumer is using, the consumer thread never wakes up.
Changing the code to use a shared lock works:
import java.util.*;
public class ProducerConsumer { private static LinkedList linkedList = new LinkedList();
public static void main(String a[]) throws InterruptedException {
final Object lock = new Object();
Thread producer = new Thread(new Runnable() {
#Override
public void run() {
synchronized (lock) {
while (linkedList.size() ==1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produced");
linkedList.add(1);
lock.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread consume = new Thread(new Runnable() {
#Override
public void run() {
// produce
synchronized (lock) {
while (linkedList.isEmpty()) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Consumed");
linkedList.removeFirst();
lock.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
producer.start();
consume.start();
producer.join();
consume.join();
}
}
Output for this is:
c:\example>java ProducerConsumer
Produced
Consumed
which I think is what you're expecting.
Btw see this other answer I wrote for a dirt-simple implementation of a queue; you are better off protecting the shared data structure than putting the code in the threads accessing the data structure, especially look at how much easier the code is to write.
Concurrency means that you can not know before runtime which Thread will end first. So you can not know which of the Consumer and Producer is launched, executed or finished first.
To help you, you can use a cyclic barrier https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html or applying the Fork/Join Framework https://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html
Your synchronized blocs just say : only one Thread at a time can execute this part of code, not execute the first and the second after.
An example of how CyclicBarrier works :
service = Executors.newFixedThreadPool(numThreadsTotal);
CyclicBarrier c = new CyclicBarrier(numThreadsToWait);
runProducer();
c.await();
runConsumer();
It will wait until the there is as much Threads as numThreadsToWait that have execute the runProducer to execute the runConsumer().
Perhaps using a Thread Pool with a size of 1 could help you, but you will loose the benefits of concurrency.
I think best what you can do, is use BlockingQueue.

Producer consumer problems without semaphores in java threads synchronization

Hi I have been trying to solve the producer consumer problem in java without semaphores. When I use single producer and single consumer then my code is working fine. But when I add more than one consumer then it is completely messing up, all the consumer threads are going into the synchronized block. I'm not sure why this is happening. Here is my code :
Producer class:
public class Producer implements Runnable {
Object SharedObject = null;
String producerName= null;
Random rn = new Random();
public Producer(Main m, String s) {
this.SharedObject = m;
this.producerName=s;
}
public Producer(Main m) {
this.SharedObject = m;
}
public void run() {
while (true) {
synchronized (SharedObject) {
if (Main.itemCount == Main.bufferSize) {
try {
System.out.println("Producer is sleeping and waiting for notification form Consumer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount++;
System.out.println(this.producerName+" Produced the item and the item count is : " + Main.itemCount);
if (Main.itemCount == 1) {
SharedObject.notify();
System.out.println("Producer Notified the cosumer to wake up");
}
}
try {
int i = rn.nextInt(100);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Consumer Class:
public class Consumer implements Runnable {
Object SharedObject = null;
String consumerName= null;
Random rn = new Random();
public Consumer(Main m, String s) {
SharedObject = m;
this.consumerName=s;
}
Consumer c= new Consumer((Main) SharedObject,consumerName);
synchronized void consume(){
synchronized (SharedObject) {
if (Main.itemCount == 0) {
try {
System.out.println(this.consumerName+" is sleeping and waiting for notify from Producer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount--;
System.out.println(this.consumerName+" consumed 1 item and the item Count is " + Main.itemCount);
if (Main.itemCount == 4) {
SharedObject.notifyAll();
System.out.println("Consumer notified the producer to wake up");
}
}
}
public void run() {
while (true) {
c.consume();
try {
int i = rn.nextInt(100);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Main Class:
public class Main {
static int itemCount = 0;
static int bufferSize = 5;
public static void main(String[] args) {
Main m = new Main();
Thread objP = new Thread(new Producer(m, "Producer1"));
Thread objC = new Thread(new Consumer(m, "Consumer1"));
Thread objC2 = new Thread(new Consumer(m, "Consumer2"));
Thread objC3 = new Thread(new Consumer(m, "Consumer3"));
objP.start();
objC.start();
objC2.start();
objC3.start();
}
}
You are using notifyAll in the producer, which wakes up all consumer threads waiting on the monitor. If you want only one consumer to wake up, you should use notify From the API documentation:
notify()
Wakes up a single thread that is waiting on this object's monitor.
notifyAll()
Wakes up all threads that are waiting on this object's monitor.
It would also be better for your consumers to actually check that they can consume a resource when they are woken up. If you want to continue to use notifyAll, a consumer should be able to be awoken, and if insufficient resource is available, go back to waiting.
I suggest printing the main.itemCount. This will make it more obvious what the problems you have are.
You have to pay attention to when you are calling notify.
Why does your producer only call notify when there is exactly one item available? Shouldn't the producer call notify whenever there is an item available?
The consumer only tells the producer to wake up when there are 4 items (isn't this full?).
Actually changing notifyAll() to notify() kindoff worked!!! thanks for ua suggestion guys. Here is my code:
Producer class:
package com.source;
import java.util.Random;
public class Producer implements Runnable {
Object SharedObject = null;
String producerName = null;
Random rn = new Random();
public Producer(Main m, String s) {
this.SharedObject = m;
this.producerName = s;
}
public Producer(Main m) {
this.SharedObject = m;
}
public void run() {
while (true) {
synchronized (SharedObject) {
if (Main.itemCount == Main.bufferSize) {
try {
System.out
.println(this.producerName + "is sleeping and waiting for notification form Consumer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount++;
System.out.println(this.producerName + " Produced the item and the item count is : " + Main.itemCount);
if (Main.itemCount == 1) {
SharedObject.notify();
System.out.println("Producer Notified the cosumer to wake up");
}
}
try {
int i = rn.nextInt(100);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Consumer Class:
package com.source;
import java.util.Random;
public class Consumer implements Runnable {
Object SharedObject = null;
String consumerName = null;
Random rn = new Random();
public Consumer(Main m, String s) {
SharedObject = m;
this.consumerName = s;
}
public void run() {
while (true) {
synchronized (SharedObject) {
if (Main.itemCount == 0) {
try {
System.out.println(this.consumerName + " is sleeping and waiting for notify from Producer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount--;
System.out.println(this.consumerName + " consumed 1 item and the item Count is " + Main.itemCount);
if (Main.itemCount == 4) {
SharedObject.notify();
System.out.println("Consumer notified the producer to wake up");
}
}
try {
int i = rn.nextInt(1000);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Main Class:
package com.source;
public class Main {
static int itemCount = 0;
static int bufferSize = 5;
public static void main(String[] args) {
Main m = new Main();
Thread objP = new Thread(new Producer(m, "Producer1"));
Thread objC = new Thread(new Consumer(m, "Consumer1"));
Thread objC2 = new Thread(new Consumer(m, "Consumer2"));
Thread objC3 = new Thread(new Consumer(m, "Consumer3"));
Thread objP2 = new Thread(new Producer(m, "Producer2"));
Thread objP3 = new Thread(new Producer(m, "Producer3"));
objP.start();
objC.start();
objC2.start();
objC3.start();
objP2.start();
objP3.start();
}
}
Once again thanks to everyone for your valuable time and suggestions.
Sounds like you are past your initial problem but here's some more feedback.
I believe your real problem was not because of notifyAll() but because your buffer tests were if tests instead of while loops. There are classic race conditions where a thread gets awaken but there are no elements in the buffer. See my notes here. So you code should be something like:
while (Main.itemCount == Main.bufferSize) {
and
while (Main.itemCount == 0) {
Calling notifyAll() exacerbated the problem but the race conditions still exist even with just notify(). As you add more consumers or another producer you will see more problems.
Here is some other feedback.
Be very careful of locks within locks. That is a bad pattern typically and one that I use very infrequently. Do you really need consume() to be synchronized?
Object instance names should start with a lowercase letter so it should be sharedObject.
Any object that you are locking on should be private final if at all possible. You wouldn't want it changing to another object.
Using Main. anything is a bad pattern. How about creating an object with the itemCount and bufferSize and then passing the same instance of that object to all of our producer and consumers? It would also be the object you would lock on.
Be careful of sprinkling your thread code with System.out.println(...) messages as others have recommended. System.out is a synchronized class so this will add locks and memory synchronization that may move or fix the problem. Yes. Debugging threaded programs is hard.

Suggestions on my implementation of Producer Consumer

I am naive in multi-threading and is trying to learn it's concepts. This is my implementation for Producer-Consumer problem. Please have a look and suggest me if it is incorrect/crude/any other suggestions that could improve my design.
static int data = 0;
static Object obj1 = new Object();
static class Producer implements Runnable {
public void run() {
produce();
}
void produce() {
while (true) {
if (data < 5){
synchronized(obj1){
System.out.println("Producing Data. Now Data is "+data++);
obj1.notifyAll();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
try {
System.out.println("Producer inactive");
synchronized(obj1){
obj1.wait();
}
System.out.println("Producer active");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
static class Consumer implements Runnable{
public void run(){
consume();
}
void consume() {
while (true) {
if (data > 0){
synchronized(obj1){
System.out.println("Consuming Data. Now Data is "+data--);
obj1.notifyAll();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
try {
System.out.println("Consumer Inactive");
synchronized(obj1){
obj1.wait();
}
System.out.println("Consumer Active");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Ok several points. Producer and Consumer usually share a data structure. The use of the static data is very odd and quite frankly makes no sense. Typically what you'll want to share is a data structure like a queue between producer and consumer. The producer will add things on to the tail of the queue and the consumer(s) will draw things from the head of the queue (FIFO - first in first out). Right now I see none of that so what exactly is it producing vs consuming?
A good producer consumer architecture doesn't care too much about what type of data is exchanged so you can pass many different types of things over it. That's where object oriented command architecture will help you out. In this example SomeMessage represents the root of some object hierarchy so a variety of messages can be exchanged.
Here is a simple example of how you should instantiate a Producer-Consumer architecture in your program:
public class SomeClient {
public void start() {
Queue sharedQueue = new LinkedList();
producer = new Producer( sharedQueue );
consumer = new Consumer( sharedQueue );
producer.start();
consumer.start();
}
}
Here is the implementation of that:
public class Producer implements Runnable {
Thread thread;
Queue queue;
public Producer(Queue queue) {
this.queue = queue;
}
public void start() {
thread = new Thread(this);
thread.start();
}
public void shutdown() {
thread.interrupt(); // request a shutdown
thread.join(); // make sure we wait until Producer.thread exits before this thread continues
}
public void run() {
try {
while( !Thread.isInterrupted() ) {
SomeMessage message = produceAMessage();
synchronized( queue ) {
queue.add( message );
queue.notifyAll();
}
}
} catch( InterruptedException ex ) {
System.out.println("Producer shutting down per request.");
} finally {
thread = null;
}
}
}
public class Consumer implements Runnable {
Thread thread;
Queue queue;
public Consumer( Queue queue ) {
this.queue = queue;
}
public void start() {
thread = new Thread( this );
thread.start();
}
public void shutdown() {
thread.interrupt(); // request a shutdown
thread.join(); // make sure we wait until Consumer.thread exits before this thread continues
}
public void run() {
try {
while( !thread.isInterrupted() ) {
SomeMessage message = take();
doSomethingWithMessage( message );
}
} catch( InterruptedException ex ) {
System.out.println("Stop processing - consumer per request.");
} finally {
thread = null;
}
}
private SomeMessage take() throws InterruptedException {
synchronized( queue ) {
queue.wait();
return queue.remove();
}
}
}
A couple of things that differ in this implementation. Producer and Consumer share a Queue instance and they use that instance to perform synchronized calls on. That way neither write or read from that structure without owning the lock. After they have either added to the queue (producer) or removed from the queue (consumer) they are free from needing to use synchronization. They are free to process without needing to communicate with each other. They trade instances of SomeMessage between each instance by adding to the tail and drawing from the head.
The take() method is very important in this code. Without the helper method you can't process the message AND release the lock. This important so that your Consumer can receive a message and let go of the lock to allow other Producers/Consumers to add/remove messages while this particular Consumer is processing a message. This keeps throughput as fast as possible.
And yes I said Producers. This architecture allows for multiple Producers AND multiple Consumers without needing to change the internals of either Producer or Consumer.
Notice that catching InterruptedException is outside the while loop. This is very important if you want a predictable program that shuts down cleanly. An InterruptedException and interrupted concept is the heart of well behaving Java threads. If you don't know under what conditions this exception is generated you'll never understand multi-threaded apps in Java. It's not a random occurrence. Java threads can't be stopped programatically. Another thread must request it to interrupt itself. And the thread must obey the request or else it won't stop. So if we get one. Shutdown. In this program we'll only get it when we call wait or notify which means while we're processing a message we won't be interrupted. Consumers will finish processing messages before halting.
Finally, it's actually much easier to implement a Producer-Consumer relationship given the concurrency libraries in Java, but this is a good example of how you do it at the lowest level of Java to understand what those libraries are doing for you.
Encapsulating the consume and produce behaviors could be more more reusable. In the code below I decoupled the shared resource synchronization issues from consumer/producer thread which could be useful in solving similar problems like Object Pool and Connection Pool.
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumer {
public static void main(String[] args) {
SyncQueue syncQueue = new SyncQueue(1);
Producer producer = new Producer(syncQueue , 10);
Consumer consumer = new Consumer(syncQueue,10);
producer.start();
consumer.start();
}
}
class SyncQueue {
private Queue<Integer> queue = new LinkedList<Integer>();
private Integer size;
public SyncQueue(Integer size) {
super();
this.size = size;
this.signalledBefore = false;
}
public synchronized void put(Integer data){
while(queue.size() == size){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.add(data);
notifyAll();
}
public synchronized Integer get(){
while(queue.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Integer data = queue.remove();
notifyAll();
return data;
}
}
class Producer extends Thread{
private SyncQueue syncQueue;
private Integer size;
public Producer(SyncQueue syncQueue, Integer size) {
this.syncQueue = syncQueue;
this.size = size;
}
#Override
public void run() {
for (Integer i = 0; i < size; i++) {
syncQueue.put(i);
System.out.println("Produced:" + i);
try {
sleep((int)Math.random()*100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread{
private SyncQueue syncQueue;
private Integer size;
public Consumer(SyncQueue syncQueue, Integer size) {
this.syncQueue = syncQueue;
this.size = size;
}
#Override
public void run() {
for (Integer i = 0; i < size; i++) {
try {
sleep((int)Math.random()*100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumed:" + syncQueue.get());
}
}
}

How to pass parameter to an already running thread in java?

How to pass parameter to an already running thread in java -- not in the constructor, & probably without using wait() (possible ??)
Something similar to a comment in How can I pass a parameter to a Java Thread?
Do you mean passing a parameter to an already running thread ? Because all the current answers are about passing parameters to new threads... – Valentin Rocher May 18 '09 at 10:43
[edited]
yes, I was looking for something like the producer/consumer pattern.
I wanted something like a thread in which has the processing & is ready
for keyboard input. The other thread is just to monitor network and pass
on the received text to the processing thread.
Maybe what you really need is blocking queue.When you create the thread, you pass the blocking queue in and the thread should keep checking if there is any element in the queue. Outside the thread, you can put elements to the queue while the thread is "running". Blocking queue can prevent the thread from quit if their is nothing to do.
public class Test {
public static void main(String... args) {
final BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
Thread running = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
String data = queue.take();
//handle the data
} catch (InterruptedException e) {
System.err.println("Error occurred:" + e);
}
}
}
});
running.start();
// Send data to the running thread
for (int i = 0; i < 10; i++) {
queue.offer("data " + i);
}
}
}
The "other thread" will have its own life, so you can't really communicate with it / pass parameters to it, unless it actively reads what you gives to it.
A thread which you allows you to communicate with it typically reads data from some buffered queue.
Have a look at ArrayBlockingQueue for instance, and read up on the Consumer-Producer pattern.
public class T1 implements Runnable {
//parameter of thread T1
public static AtomicBoolean flag = new AtomicBoolean();
#Override
public void run() {
}
}
public class T2 implements Runnable {
#Override
public void run() {
//parameter to an already running thread
T1.flag.set(true);
}
}
What about such way:
class TestRun implements Runnable
{
private int testInt = -1;
public void setInt(int i)
{
this.testInt = i;
}
#Override
public void run()
{
while (!isFinishing())
{
System.out.println("Working thread, int : " + testInt);
try
{
Thread.sleep(2500);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
.....
TestRun first = new TestRun();
TestRun second = new TestRun();
(new Thread(first)).start();
(new Thread(second)).start();
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
}
first.setInt(101);
second.setInt(102);

My Produce Consumer Hangs

Please copy the program below and try running in your IDE. It's a simple Produce Consumer implementation - it runs fine when I use one Producer and one Consumer thread but fails when using 2 each. Please let me know the reason why this program hangs or is there anything else wrong with it.
import java.util.LinkedList;
import java.util.Queue;
public class PCQueue {
private volatile Queue<Product> productQueue = new LinkedList<Product>();
public static void main(String[] args) {
PCQueue pc = new PCQueue();
Producer producer = new Producer(pc.productQueue);
Consumer consumer = new Consumer(pc.productQueue);
new Thread(producer, "Producer Thread 1").start();
new Thread(consumer, "Consumer Thread 1").start();
new Thread(producer, "Producer Thread 2").start();
new Thread(consumer, "Consumer Thread 2").start();
}
}
class Producer implements Runnable {
private Queue<Product> queue = null;
private static volatile int refSerialNumber = 0;
public Producer(Queue<Product> queue) {
this.queue = queue;
}
#Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.peek() != null) {
try {
queue.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
queue.add(new Product(++refSerialNumber));
System.out.println("Produced by: "
+ Thread.currentThread().getName() + " Serial Number: "
+ refSerialNumber);
queue.notify();
}
}
}
}
class Consumer implements Runnable {
private Queue<Product> queue = null;
public Consumer(Queue<Product> queue) {
this.queue = queue;
}
#Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.peek() == null) {
try {
queue.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Product product = queue.remove();
System.out.println("Consumed by: "
+ Thread.currentThread().getName() + " Serial Number: "
+ product.getSerialNumber());
queue.notify();
}
}
}
}
class Product {
private int serialNumber;
public Product(int serialNumber) {
this.serialNumber = serialNumber;
}
public int getSerialNumber() {
return serialNumber;
}
}
The problem is that you are using queue.notify() which will only wake up a single Thread waiting on the Queue. Imagine Producer 1 calls notify() and wakes up Producer 2. Producer 2 sees that there is something in the queue so he doesn't produce anything and simply goes back to the wait() call. Now both your Producers and Consumers are all waiting to be notified and nobody is left working to notify anyone.
To solve the problem in your code, use queue.notifyAll() to wake up every Thread blocked at a wait(). This will allow your consumers to run.
As a note, your implementation limits the queue to having at most one item in it. So you won't see any benefit from the second set of producers and consumers. For a better all around implementation, I suggest you look at BlockingQueue and use an implementation which can be bounded, for instance, the ArrayBlockingQueue. Instead of synchronizing and using wait/notify, simply use BlockingQueue.offer() and BlockingQueue.take().
instead of queue.notify() use queue.notifyAll()

Categories

Resources