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?
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"
Comments
-
Bernard over 1 year
In a
Thread
After calling thestart()
as you know it will call therun()
function in theRunnable
class. In therun()
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 callingThread.sleep(6000);
Is there any other way to stay there in the run function?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?
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?Should I say
while(Thread.isAlive)
and then kill the threat when I receive the "Bye" by callingThread.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 over 11 yearsBut what if I want to stay in the run? The while loop is fine or?
-
taufique over 11 yearsyeah while loop is fine. run the while loop and whenever you get "bye" call return.
-
Bernard over 11 yearsDo you mean while loop inside the run method?
-
taufique over 11 yearsyeah. while have to be inside the run method
-
Bernard over 11 yearsThanks for your answer. it really helps. I appreciate it ;)
-
Riptyde4 about 9 yearsDoes 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 about 9 yearsSee 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 over 4 yearsthis is bad, running in a loop is CPU consuming
-
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 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 over 4 yearswith the below solution of semaphore at least we can hope that the waiting is done in a sensible manner
-
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 whennotify()
(ornotifyAll()
) is called. As I mentioned, this is demonstrated in the web crawler example I linked. -
Adriaan Koster over 4 yearsWhy not just use wait/notify for this?