how to set boolean flag of thread-1 from thread-2 in Java multithreading
Asked Answered
C

4

1

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!!

Collbaith answered 4/3, 2014 at 18:53 Comment(2)
I think you are inventing the wheel. For every thread java already has internal interruption flag. You just need to call interrupt() method on your first thread and handle interruption there in a proper way.Monochasium
@ferrerverck: I know about the interrupt flag. I need to interrupt thread-1 from thread-2. please demonstrate how to achieve this?Collbaith
B
3

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.

Batik answered 4/3, 2014 at 19:5 Comment(0)
C
1

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);
        ...
    }
Crum answered 4/3, 2014 at 19:1 Comment(0)
P
0

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

Parlor answered 4/3, 2014 at 18:57 Comment(2)
isDone flag is in Thread-1 how does Thread-2 has access to itCollbaith
You should create this method in Thread 1, and thread 2 only has to wait for it to be true. synchronized tells the other thread to "wait" because the data is currently being accessed or altered by another thread; as stated in the article, you can do synchronized statements too, but it is not recommended.Parlor
S
0

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.

Submaxillary answered 4/3, 2014 at 19:2 Comment(2)
plz explain how the other thread is going to call this method?Collbaith
Technically, the thread itself doesn't actually call the method. The RunningAvg object that is executing in Thread-2 would call it. RunningAvg would have a pointer to your NumGen object (passed in the constructor or a setter), and it would call numGen.setIsDone(true) inside the while loop in its run() method.Submaxillary

© 2022 - 2024 — McMap. All rights reserved.