views:

108

answers:

3

How can I make a thread run only if the other thread is running too, meaning, if I return from run in one thread, then I want the other to stop running too, my code looks something like this:

    ClientMessageHandler clientMessagehandler = new ClientMessageHandler();
  ServerMessageHandler serverMessagehandler = new ServerMessageHandler();
  Thread thread1 = new Thread(serverMessagehandler);
  Thread thread2 = new Thread(clientMessagehandler);
  thread2.start();
  thread1.start();

i want to cause thread1 to stop running when thread2 stops running. edit: detecting when thread2 stops running in order stop thread1 from running, and not how to stop thread1 from running thanks

+2  A: 

Edit for question clarification

I see two immediate options:

Option 1. Have the ClientMessageHandler implementation terminate the ServerMessageHandler as it terminates. This means the client needs a reference to the server thread.

public class ClientMessageHandler implements Runnable {
    Thread serverThread;
    public ClientMessageHandler(Thread srvThread) {
        this.serverThread = srvThread;
    }
    public void run() {
        try {
            while (true) { ... }
        } finally {
           serverThread.interrupt();
        }
   }
}

Option 2. Use thread2.join() or a CountDownLatch to wait for thread2 to terminate. When control returns from the join (or CountDownLatch#await()).

ClientMessageHandler clientMessagehandler = new ClientMessageHandler();
ServerMessageHandler serverMessagehandler = new ServerMessageHandler();
Thread thread1 = new Thread(serverMessagehandler);
Thread thread2 = new Thread(clientMessagehandler);
thread2.start();
thread1.start();

thread2.join(); //blocks until the client terminates
thread1.interrupt();

Make sure that inside thread1's run method, you have some logical place where you can check the interrupt status (Thread#isInterrupted()) and decide to terminate. Also, you must take care to handle InterruptedException properly and either terminate or reset the interrupt flag.

Tim Bender
It won't stop immediately... [Edit] yes fine, edit it in afterwards.
BalusC
@BalusC Yeah, I know, I'm trying something Tom Hawtin blogged about.
Tim Bender
I meant, detecting when thread2 stops running in order stop thread1 from running, and not how to stop thread1 from running
Noona
@Noona, I did some heavy edits to compensate for your clarifications.a
Tim Bender
+1  A: 

A Thread will only stop when the run() method returns. The Thread#interrupt() only signals that a request for interruption has made. You still have to write the code in run() method accordingly that it periodically checks Thread#isInterrupted() and handle accordingly. E.g. check for it on every unit of task the Thread is doing, or on every certain progress when sort of progresslistener is attached.

BalusC
Thread2 will not be interrupted, it simply returns from its run method, I tried passing an argument in the clientMesasgehandler, and in the loop condition inside servertMesasgehandler i check if thread1.isAlive(), but thread1 still returns even when thread2 is supposed to still be running, i.e it returns after one iteration in the run loop. BTW, clientMesasgehandler also contains an infinite loop in its run method.
Noona
I think you missed the point. Thread1 **must** return from `run()` method whenever you'd like to stop the thread. You need to call `Thread#interrupt()` on Thread1. You need to rewrite the `run()` method of Thread1 so that it regularly checks if `Thread#isInterrupted()` returns `true` and if so then return from `run()` method.
BalusC
but thread2 will not be interrupted, it just returns from its run method and is no longer alive, in this case, I want to return from thread1 too.
Noona
Pass Thread1 during construction of Thread2 and let Thread2 interrupt Thread1 when it's about to return. Either that, or control it in the main thread by joining Thread2 and then immediately interrupting Thread1 thereafter (as pointed in Tim's answer).
BalusC
A: 

This minimal example should demonstrate the basic idea:

import java.io.*;
import java.util.concurrent.LinkedBlockingQueue;

public class Test {

    static LinkedBlockingQueue<String> msgBuf = new LinkedBlockingQueue<String>();
    static volatile boolean keepRunning = true;
    static Thread thread1, thread2;

    public static void main(String[] args) throws IOException {
        ClientMessageHandler clientMessagehandler = new ClientMessageHandler();
        ServerMessageHandler serverMessagehandler = new ServerMessageHandler();
        thread1 = new Thread(serverMessagehandler);
        thread2 = new Thread(clientMessagehandler);
        thread2.start();
        thread1.start();
    }

}

class ClientMessageHandler implements Runnable {
    public void run() {
        while (Test.keepRunning) {
            try {
                String msg = Test.msgBuf.take();
                System.out.println("Eating " + msg);
            } catch (InterruptedException ie) {
            }
        }
    }
}

class ServerMessageHandler implements Runnable {
    public void run() {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String in;
        try {
            while (!(in = br.readLine()).equals("quit")) {
                System.out.println("Feeding " + in);
                Test.msgBuf.offer(in);
            }
        } catch (IOException e) {
        }
        Test.keepRunning = false;
        Test.thread2.interrupt();
    }
}
aioobe