Reputation: 31262
I am writing a simple multithreaded
application that involves three threads:
Thread-1
, Thread-2
and main
.
Thread-1
is a random number
generator class that produces random doubles
and feeds to Thread-2
.
Thread-2
consumes the numbers to calculate the average .I have used PipedOutputStream
that Thread-1
feeds with random numbers
. Thread-2
uses PipedInputStream
to eat up the random numbers
.
The question is::
if the average exceeds 1E5 in Thread-2
, I want to signal Thread-1
to stop producing numbers. I have a boolean flag
in Thread-1
that needs to be turned on. How can I achieve this?
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Random;
//
class NumGen extends Thread {
PipedOutputStream pos;
DataOutputStream dos;
boolean isDone=false;
public NumGen(PipedOutputStream pos){
this.pos=pos;
dos=new DataOutputStream(pos);
}
public void run(){
while (!isDone){
Random rand = new Random();
try {
dos.writeDouble(rand.nextDouble()+100.0);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class RunningAvg extends Thread {
PipedInputStream pis;
DataInputStream dis;
Double avg;
int count;
Double runningTotal;
public RunningAvg(PipedInputStream pis){
this.pis=pis;
dis=new DataInputStream(pis);
runningTotal=0.0;
avg=0.0;
}
public void run(){
try {
while (dis.available()>0){
count+=1;
runningTotal+=dis.readDouble();
avg=runningTotal/count;
System.out.printf("The average in count no : %s is %s%n",count,avg);
//if avg>1E5
//set NumGen.isDone=true
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class InterThreadComm {
public static void main(String[] args){
try {
PipedOutputStream pos= new PipedOutputStream();
PipedInputStream pis = new PipedInputStream(pos);
NumGen ng = new NumGen(pos);
RunningAvg ra = new RunningAvg(pis);
ng.start();
ra.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
PS: The code as it is runs forever without printing anything on console which I am yet to figure out why!!
Upvotes: 1
Views: 5297
Reputation: 27190
I would have the main() routine create a new AtomicBoolean object, and I would pass references to the object to the constructors of both Thread classes. The RunningAvg.run() method can set the AtomicBoolean, and the NumGen.run() method can examine it.
class NumGen extends Thread {
...
AtomicBoolean isDone;
public NumGen(PipedOutputStream pos, AtomicBoolean isDone){
...
this.isDone = isDone;
}
public void run(){
while (!isDone.get()){
...
}
}
}
class RunningAvg extends Thread {
...
AtomicBoolean isDone;
public RunningAvg(PipedInputStream pis, AtomicBoolean isDone){
...
this.isDone = isDone;
}
public void run(){
try {
while (dis.available()>0){
...
if (avg > 1E5) {
isDone.set(true);
...
}
}
...
}
public class InterThreadComm {
public static void main(String[] args){
try {
...
AtomicBoolean isDone = new AtomicBoolean(false);
NumGen ng = new NumGen(pos, isDone);
RunningAvg ra = new RunningAvg(pis, isDone);
...
}
Upvotes: 1
Reputation: 8657
You could use AtomicBoolean
and pass it to the both threads, Atomic types is accessable throw multithreading also thread safe.
first declare you flag isDone
as AtomicBoolean
private AtomicBoolean isDone;
then declare one AtomicBoolean
object and pass it to the both threads
PipedOutputStream pos= new PipedOutputStream();
PipedInputStream pis = new PipedInputStream(pos);
AtomicBoolean isDone = new AtomicBoolean();
NumGen ng = new NumGen(pos, isDone);
RunningAvg ra = new RunningAvg(pis, isDone);
ng.start();
ra.start();
finally once you want to stop generting numbers ask Thread-2
to set the isDone
false.
Upvotes: 3
Reputation: 1003
I would create a method called setIsDone() in NumGen.
public void setIsDone(boolean isDone) {
this.isDone = isDone;
}
Your other thread can call this when it is time to for NumGen to finish.
Also, the general recommendation is that in most cases you should implement the Runnable interface instead of subclassing Thread directly, but that is just a rule of thumb not a hard and fast rule.
Upvotes: 0
Reputation: 126
You need to create a method that is accessible in both, using sychronized.
for ex:
public synchronized boolean getDone()
{
return isDone;
}
Otherwise you will have trouble keeping track of the variable between threads.
Here is a link that should help :http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Upvotes: 0