bobthemac
bobthemac

Reputation: 1172

End Java threads after a while statement has been run

I am having an issue ending threads once my program my has finished. I run a threaded clock object and it works perfectly but I need to end all threads when the time ´==´ one hour that bit seems to work I just need to know how to end them. Here is an example of the code I have and this is the only thing that runs in the run method apart from one int defined above this code.

    @Override
    public void run()
    {
        int mins = 5;
        while(clock.getHour() != 1)
        {
            EnterCarPark();
            if(clock.getMin() >= mins)
            {
                System.out.println("Time: " + clock.getTime() + " " + entryPoint.getRoadName() + ": " + spaces.availablePermits() + " Spaces");
                mins += 5;
            }
        }
    }

But when you keep watching the threads that are running in the debug mode of netbeans they keep running after an hour has passed not sure how to fix this. I have tried the interrupt call but it seems to do nothing.

enter image description here

Upvotes: 7

Views: 5350

Answers (7)

Arkantos
Arkantos

Reputation: 6608

Using Thread.interrupt() will not stop the thread from running, it merely sends a signal to you thread. It's our job to listen for this signal and act accordingly.

Thread t = new Thread(new Runnable(){
              public void run(){
                 // look for the signal
                 if(!Thread.interrupted()){
                     // keep doing whatever you're doing
                 }

              }
         });

 // After 1 hour
 t.interrupt();

But instead of doing all this work, consider using an ExecutorService. You can use Executors class with static methods to return different thread pools.

Executors.newFixedThreadPool(10)

  • creates a fixed thread pool of size 10 and any more jobs will go to queue for processing later

Executors.newCachedThreadPool()

  • starts with 0 threads and creates new threads and adds them to pool on required basis if all the existing threads are busy with some task. This one has a termination strategy that if a thread is idle for 60 seconds, it will remove that thread from the pool

Executors.newSingleThreadExecutor()

  • creates a single thread which will feed from a queue, all the tasks that're submitted will be processed one after the other.

You can submit your same Runnable tasks to your thread pool. Executors also has methods to get pools to which you can submit scheduled tasks, things you want to happen in future

ExecutorService service = Executors.newFixedThreadPool(10);
service.execute(myRunnableTask);

Coming to your question, when you use thread pools, you have an option to shut down them after some time elapsed like this

service.shutdown();
service.awaitTermination(60, TimeUnit.MINUTES);

Few things to pay attention

shutdown() Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.

awaitTermination() is waiting for the state of the executor to go to TERMINATED. But first the state must go to SHUTDOWN if shutdown() is called or STOP if shutdownNow() is called.

Upvotes: 1

Toby Derrum
Toby Derrum

Reputation: 309

Have you considered using an ExecutorService ? It behaves more predictably and avoids the overhead of thread creation. My suggestion is that you wrap your while loop within one and set a time limit of 1 hr.

Upvotes: 1

Thirler
Thirler

Reputation: 20760

There are two ways to stop a thread in a nice way, and one in an evil way.

For all you need access to the object of the thread (or in the first case a Runnable class that is executed on that thread).

So your first task is to make sure you can access a list of all threads you want to stop. Also notice that you need to make sure you are using threadsafe communication when dealing with objects used by several threads!

Now you have the following options

Interrupt mechanisme

Call Thread.interrupt() on each thread. This will throw an InterruptedException on the thread if you are in a blocking function. Otherwise it will only set the isInterrupted() flag, so you have to check this as well. This is a very clean and versatile way that will try to interrupt blocking functions by this thread. However many people don't understand how to nicely react to the InterruptedException, so it could be more prone to bugs.

isRunning flag

Have a boolean 'isRunning' in your thread. The while loop calls a function 'stopRunning()' that sets this boolean to false. In your thread you periodically read this boolean and stop execution when it is set to false. This boolean needs to be threadsafe, this could be done by making it volatile (or using synchronized locking).

This also works well when you have a Runnable, which is currently the advised way of running tasks on Threads (because you can easily move Runnables to Threadpools etc.

Stop thread (EVIL)

A third and EVIL and deprecated way is to call Thread.stop(). This is very unsafe and will likely lead to unexpected behavior, don't do this!

Upvotes: 10

Jim W
Jim W

Reputation: 512

It's a bad practice to externally terminate threads or to rely on external mechanisms like kill for proper program termination. Threads should always be designed to self-terminate and not leave resources (and shared objects) in a potentially indeterminate state. Every time I have encountered a thread that didn't stop when it was supposed to, it was always a programming error. Go check your code and then step through the run loop in a debugger.

Regarding your thread, it should self-terminate when the hour reaches 1, but if it is below or above 1, it will not terminate. I would make sure that clock's hour count reaches one if minutes go past 59 and also check that it doesn't somehow skip 1 and increment off in to the sunset, having skipped the only tested value. Also check that clock.getHour() is actually returning the hour count instead of a dummy value or something grossly incorrect.

Upvotes: 1

James_pic
James_pic

Reputation: 3307

If these threads are still running after your main program has finished, then it may be appropriate to set them as daemon threads. The JVM will exit once all non-daemon threads have finished, killing all remaining daemon threads.

If you start the threads like:

Thread myThread = new MyThread();
myThread.start();

Then daemon-izing them is as simple as:

Thread myThread = new MyThread();
myThread.setDaemon(true);
myThread.start();

Upvotes: 1

ZakiMak
ZakiMak

Reputation: 2102

A volatile variable shared by all the Threads should help to achieve the goal. The importance of a volatile variable is that each of the Threads will not cache or have local copy but will need to directly read from the main memory. Once it is updated, the threads will get the fresh data.

    public class A{
     public static volatile boolean letThreadsRun = true;
    }

    // inside your Thread class
    @Override
    public void run()
    {    // there will come a point when A.letThreadsRun will be set to false when desired
         while(A.letThreadsRun)
        {

        }
    }

If two threads are both reading and writing to a shared variable, then using the volatile keyword for that is not enough. You need to use synchronization in that case to guarantee that the reading and writing of the variable is atomic.

Here are links that may help you to grasp the concept:

http://tutorials.jenkov.com/java-concurrency/volatile.html

http://java.dzone.com/articles/java-volatile-keyword-0

Upvotes: 1

Nick Louloudakis
Nick Louloudakis

Reputation: 6005

Make sure that the loop inside every thread finishes - if it does in all the threads, it does not make sense that there are prints in the output. Just note that what you are checking in each loop condition check if the current hour is not 1 PM, not if an hour has not passed.

Also, your threads garbage collected, which means that the Garbage Collector is responsible for their destruction after termination - but in that case they should not output anything.

Upvotes: 2

Related Questions