简体   繁体   中英

Thread isn't removed after it has stopped running

I have a Service which is running on a thread. When I need the thread to stop running I am using this code
this.serviceThread.interrupt(); this.serviceThread = null;

At some point I need to recreate the thread again

this.serviceThread = new Thread() 
        {
            public void run() 
            {
                TheService.this.serviceProcessThread();
            }
        };
        this.serviceThread.start();

However, it still seems like the previous Thread is still alive and running because it is listed in the list of currently running threads. This list just keeps growing every time I try to stop and create a new thread. Is this normal? Is there anyway I can get rid of those old threads?

I mainly just want to know if that list of threads means they are still there and, if so, how can I remove them. Thanks!

EDIT: This is how I am handling running/stopping the thread

public void startProcessThread()
{
    this.shutdown = false;
    this.serviceThread = new Thread() 
    {
        public void run() 
        {
            TheService.this.serviceProcessThread();
        }
    };
    this.serviceThread.start();
}
private void serviceProcessThread()
{
    do 
    {
        try 
        {
            this.getCommands();

            if (this.tasks.size() > 0)
                this.processTasks();

            if (!this.shutdown)
            {
                Thread.sleep(ServiceSleepTime);
            }
        }
        catch (Exception e) 
        {
            this.logException("serviceProcessThread", e);
        }
    } 
    while (!this.shutdown);
    if(this.serviceThread != null)
    {
        this.serviceThread.interrupt();
        this.serviceThread = null;

    }

}

The first thing you must face is that a thread cannot be forcibly stopped without potentially adverse effects on the whole Java process. This is why Java introduced the mechanism of thread interruption : a common, cooperative mechanism to gracefully stop a thread.

The cooperative aspect is key: whatever you do in your thread's implementation code, you must ensure that it is interruptible. A short checklist:

  • if you have blocking calls (those which arrest the thread while waiting on a condition), they must be interruptible (basically, declare to throw InterruptedException );

  • you must catch and handle the InterruptedException properly, by performing any due cleanup and making the top-level run method return;

  • if you have implemented a long-running loop, you must ensure that it checks the Thread.currentThread().isInterrupted() flag periodically, and breaks if the thread was interrupted;

  • if you cede control any 3rd party code, make sure that this code is interruptible.

Also keep in mind that the lifecycle of Thread as a Java object has nothing to do with the actual thread of execution. Thread is merely a handle object which lets you manage the underlying thread, much as a File is a handle for a filesystem entity. Setting a File reference to null does not delete the file from the system.

Update

Your implementation code could be fixed by not swallowing the InterruptedException .

    try {
        this.getCommands();
        if (this.tasks.size() > 0)
            this.processTasks();
        if (!this.shutdown)
            Thread.sleep(ServiceSleepTime);
    }
    catch (InterruptedException e) {
        this.shutdown = true;
    }
    catch (Exception e) 
    {
        this.logException("serviceProcessThread", e);
    }

Also, this part is redundant:

if(this.serviceThread != null)
{
    this.serviceThread.interrupt();
    this.serviceThread = null;

}

Here you attempt to interrupt your own (current) thread. The point was that the thread should be interrupted from another thread.

The .interrupt() does not cause a thread to exit unless you check for the interrupted status, via something like:

if (Thread.interrupted()) {
    skipRemainingActions();
}

or

while(!Thread.interrupted())
{
    doStuff();
}

if there is still code to run in the thread, it will continue to run, even if you call interrupt on it

If you are not doing anything concurrently what you need to do this is create a single thread and post task to it using handler.

There is very good article here: http://mindtherobot.com/blog/159/android-guts-intro-to-loopers-and-handlers/

You can also use AsyncTask to do the same thing- http://developer.android.com/reference/android/os/AsyncTask.html

If you have task running concurrently you can use executeOnExecutor() method of AsyncTask refer- http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor(java.util.concurrent.Executor , Params...)

Not a solution to your problem but, this does not do what you think it does:

Thread t = new Thread(new MyRunnableTask());
t.start();
t = null;

The t.start() call creates the new thread. NOTE: I said "thread", not "Thread". A (big T) Thread is an object that can be used to create and manage a (little t) thread. Once the (little t) thread is started, it has a life of its own.

When you set the local variable t to null, all you are doing is erasing your reference to the (big T) Thread object that manages the (little t) thread. The (big T) Thread object is unaffected: It will continue to exist as long as the (little t) thread is running. The (little t) thread is unaffected: It will continue to do whatever it does. The only thing that changes when you set t to null, is that you no longer have any control over the new thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM