After starting a thread how could we keep the run function running? I have bunch of ideas but I'm not sure which is more professional?

22,995

Solution 1

In the simplest case just let your run method do its work and terminate when appropriate, something like this:

public void run() {
    boolean running = true;
    while(running) {
        running = doWork();
        if (Thread.interrupted()) {
            return;
        }
    }
}

Here the process stops when the doWork() method returns false. It is also good style to allow your thread to be interrupted, especially if it needs to run for a long time, see this tutorial. For any of this to work, doWork() should return regularly. Note you cannot restart threads, once the run method has returned the thread is reclaimed by the system.

If you need more control over your threads you could create separate Worker and ThreadManager classes.

To let the ThreadManager terminate the Worker, create a volatile boolean field in your Worker which is checked periodically:

public class Worker extends Thread {

    private volatile boolean running;

    public void run() {
        running = true;
        while(running) {
            running = doWork();
            if (Thread.interrupted()) {
                return;
            }
        }
    }

    public void stopRunning() {
        running = false;
    }
}

The Worker ends when interrupted or when the work is completed. Also the ThreadManager can request the Worker to stop by invoking the stopRunning() method.

If your thread runs out of work it could also call the wait() method on the ThreadManager. This pauses the thread until it is notified that there is new work to do. The ThreadManager should call notify() or notifyAll() when new work arrives (ThreadManager is used as a monitor in this example).

With this approach you can keep the Worker simple and only concerned with doing the work. The ThreadManager determines the number of threads and makes work available to them but does not need to know details of the actual work. One step further would be to split out 'work' into a separate class too, which you could call Job. An example of this can be found in my webcrawler example. This could be useful for passing new work from the ThreadManager to the worker thread.

EDIT: clarification: If the thread doesn't do any work and just needs to wait for some condition, don't use an iteration to wait, but use either wait/notify (see the webcrawler example I gave) or a simple callback when the condition arises.

Solution 2

I know this is late, but this is a much better implementation and avoids heavy CPU usage by busy waiting - Allows context switching when the thread is waiting for a signal.

Setting the semaphore to a value of 0 ensures that when the thread attempts to acquire permission to continue, it does not get it and waits. When you release the semaphore, the count is increased by 1, allowing the thread to continue and the count is decreased back to 0.

In main:

Semaphore sem = new Semaphore(0);
Worker t = new Worker(sem);
t.start();'

// The thread is now running but waiting, signal the semaphore to start work
sem.release();

The Thread

public class Worker(Semaphore sem) extends Thread {

    public void run() {
        sem.acquire();
        doWork();
    }
}

Solution 3

just return from the run() when you get "bye"

Share:
22,995
Bernard
Author by

Bernard

Love programming...

Updated on August 22, 2022

Comments

  • Bernard
    Bernard over 1 year

    In a Thread After calling the start() as you know it will call the run() function in the Runnable class. In the run() function I want the thread stays as long as it receive the "Bye" message from the client. If i put them in the while loop it takes heaps of memory i think and I'm not using the power of thread. By the way i don't want my thread sleep in the run function by calling Thread.sleep(6000); Is there any other way to stay there in the run function?

    1. If the answer is join where and how and use it? Should I pop it at the beginning of the run function and it stays there until I send the "Bye" from client?

    2. Should I say while((request=in.readLine())!=null){? It did not work because I think it will lose the connection with the client or better say client losing the connection?

    3. Should I say while(Thread.isAlive) and then kill the threat when I receive the "Bye" by calling Thread.stop which is little bit dangerous?

    Here is my simplified code:

    while(true)
            {   
                ClientWorker w;
                try
                {                   
                    w = new ClientWorker(serverSocket.accept());
                        Thread t = new Thread(w);
                        t.start();
                    }
    ......  }
    
        class ClientWorker implements Runnable {
            public ClientWorker(Socket incoming)
            {
                myList = my;
                this.incoming = incoming;
            }
        public synchronized  void run()
        {
             in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
    .
    .
    ..
    ...
    }
    
  • Bernard
    Bernard over 11 years
    But what if I want to stay in the run? The while loop is fine or?
  • taufique
    taufique over 11 years
    yeah while loop is fine. run the while loop and whenever you get "bye" call return.
  • Bernard
    Bernard over 11 years
    Do you mean while loop inside the run method?
  • taufique
    taufique over 11 years
    yeah. while have to be inside the run method
  • Bernard
    Bernard over 11 years
    Thanks for your answer. it really helps. I appreciate it ;)
  • Riptyde4
    Riptyde4 about 9 years
    Does anyone know of a way to do this without busy waiting? Maybe a condition variable? I'm not sure of the java syntax for that.
  • Adriaan Koster
    Adriaan Koster about 9 years
    See the webcrawler example above, it uses the java wait/notify mechanism to avoid busy waiting. Another approach is the Observer pattern which uses an asynchronous callback to notify waiters of an event.
  • Manu de Hanoi
    Manu de Hanoi over 4 years
    this is bad, running in a loop is CPU consuming
  • Adriaan Koster
    Adriaan Koster over 4 years
    @ManudeHanoi 'Busy waiting' (en.wikipedia.org/wiki/Busy_waiting) is bad, meaning a thread is iterating just to check for a certain condition. My example is not a busy wait situation; the thread is doing work in the doWork() method. The periodic returning of doWork() allows the thread to check for Thread.isInterrupted() andrunning == false, allowing the thread to be managed by an external process. This is considered good practice in thread programming.
  • Manu de Hanoi
    Manu de Hanoi over 4 years
    @AdriaanKoster If the thread had work to do, keeping it alive would be trivial. The issue is how to keep the thread alive and low on CPU when it's got nothing to do in order to avoid the cpu expensive creation of new threads each time there is work to do. In the case the thread has no work to do the incessant calls to "Thread.isInterrupted()" will consume CPU
  • Manu de Hanoi
    Manu de Hanoi over 4 years
    with the below solution of semaphore at least we can hope that the waiting is done in a sensible manner
  • Adriaan Koster
    Adriaan Koster over 4 years
    @ManudeHanoi In the example code I gave the Thread returns from the run method if there is no more work, so no incessant calls to Thread.isInterrupted() will happen. I already clarified my answer regarding busy waiting after your first 'this is bad' comment. If there is no work to be done the thread should call wait() which yields the underlying system thread to the pool but can still resume its task when notify() (or notifyAll()) is called. As I mentioned, this is demonstrated in the web crawler example I linked.
  • Adriaan Koster
    Adriaan Koster over 4 years
    Why not just use wait/notify for this?