Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly stop a thread that is waiting for input from stdIn?

I've implemented a simple chat application that receives messages and redirects them to all users because I'm learning about parallel programming.

The client has two threads: One for listening the server and other (the main thread) to write to the server.

These are the codes used to implement this:

Main Thread:

    try {
        Thread listener = new Thread(new Receiver(in));
        listener.start();
        while (listener.isAlive()) {
            out.println(stdIn.readLine());
        }
        out.close();
        in.close();
        clientSocket.close();
    } catch (IOException e) {
        System.err.println("Error trying to send text to server" + e.getMessage());
    }

Runnable for second thread:

public class Receiver implements Runnable {

    private BufferedReader in;

    public Receiver(BufferedReader serverInput) {
        this.in = serverInput;
    }

    @Override
    public void run() {
        String responseLine;
        try {
            while ((responseLine = in.readLine()) != null) {
                System.out.println(responseLine);

                if (responseLine.contains("Bye")) break;
            }
        } catch (IOException e) {
                System.err.println("Erro ao receber mensagem do servidor: " + e.getMessage());
        }
    }
}

The client is supposed to send a message (#quit) in order to quit the chat to which the server will respond with a message (Bye) that will finish the client app.

How do I stop the main thread after the receiver thread has stopped it's life cicle?

I used the isAlive() method to finish it, but after the user sends the #quit message the thread is still alive and it falls again on stdIn.readline() which interrupts the thread until the user sends another message even though he's already disconnected.

I tried implementing another thread (called sender) to send messages to the server and using listener.join() on the main thread to interrupt the sender thread with Thread.interrupt(), but the sender thread still falls on the stdIn.readline() method and i don't know how to properly interrupt the IO.

if anyone wants to read the full code, it's available in this github page.

like image 523
Eduardo macedo Avatar asked Oct 17 '22 23:10

Eduardo macedo


1 Answers

@Override
public void run() {
    String responseLine;
    try {
        while(!isInterrupted()) 
        while ((responseLine = in.readLine()) != null) {
            System.out.println(responseLine);

            if (responseLine.contains("Bye")) break;
        }
    } catch (IOException e) {
            System.err.println("Erro ao receber mensagem do servidor: " + e.getMessage());
    }
}

From another thread, call interrupt() on the thread in order to shut it down

for example, before you print the stdInput check if it's "bye" then call interrupt


you can also use a flag like isRunning and call a method shutdown()

//member variable 
 private static volatile boolean isRunning = true;

public static void shutdown()
    {
        running = false;
    }

    public void run()
    {
        while( running )
        {
            //do whatever.
        }
like image 114
Bishoy Kamel Avatar answered Nov 15 '22 05:11

Bishoy Kamel