我有一个在线程上运行的服务。当我需要线程停止运行时,我正在使用此代码
this.serviceThread.interrupt();
this.serviceThread = null;
在某些时候我需要重新创建线程
this.serviceThread = new Thread()
{
public void run()
{
TheService.this.serviceProcessThread();
}
};
this.serviceThread.start();
但是,它似乎仍然活着并且正在运行,因为它列在当前运行的线程列表中。每次我尝试停止并创建新线程时,此列表都会不断增长。这是正常的吗?无论如何我可以摆脱那些旧线程吗?
我主要想知道线程列表是否仍然存在,如果是,我该如何删除它们。谢谢!
编辑:这就是我处理运行/停止线程的方法
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;
}
}
答案 0 :(得分:3)
您必须面对的第一件事是不能强行停止线程而不会对整个Java进程产生潜在的负面影响。这就是为什么Java引入了线程中断的机制:一种通用的协作机制来优雅地停止线程。
协作方面是关键:无论您在线程的实现代码中执行什么操作,都必须确保它是可中断的。简短的清单:
如果你有阻止调用(那些在等待某个条件时阻止线程),它们必须是可中断的(基本上,声明要抛出InterruptedException
);
您必须通过执行任何适当的清理并使顶级InterruptedException
方法返回来正确捕获并处理run
;
如果已实现长时间运行的循环,则必须确保它定期检查Thread.currentThread().isInterrupted()
标志,并在线程被中断时中断;
如果您放弃控制任何第三方代码,请确保此代码可以中断。
还要记住,Thread
作为Java对象的生命周期与实际的执行线程无关。 Thread
只是一个句柄对象,它允许您管理底层线程,就像File
是文件系统实体的句柄一样。将File
引用设置为null
不会从系统中删除该文件。
您的实施代码可以通过不吞咽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);
}
此外,这部分是多余的:
if(this.serviceThread != null)
{
this.serviceThread.interrupt();
this.serviceThread = null;
}
在这里,您尝试中断自己的(当前)线程。关键是该线程应该从另一个线程中断。
答案 1 :(得分:0)
除非通过以下方式检查中断状态,否则.interrupt()不会导致线程退出:
if (Thread.interrupted()) {
skipRemainingActions();
}
或
while(!Thread.interrupted())
{
doStuff();
}
如果仍有代码在线程中运行,它将继续运行,即使你在其上调用中断
答案 2 :(得分:0)
如果您没有同时执行任何操作,则需要创建一个线程并使用处理程序向其发布任务。
这里有一篇非常好的文章:http://mindtherobot.com/blog/159/android-guts-intro-to-loopers-and-handlers/
您也可以使用AsyncTask执行相同的操作 - http://developer.android.com/reference/android/os/AsyncTask.html
如果你有并发运行的任务,可以使用AsyncTask的executeOnExecutor()方法参考 - http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor(java.util.concurrent.Executor,Params ...)
答案 3 :(得分:0)
不是您问题的解决方案,但是,这不符合您的想法:
Thread t = new Thread(new MyRunnableTask());
t.start();
t = null;
t.start()
调用会创建新线程。注意:我说“线程”,而不是“线程”。 (大T)线程是一个可用于创建和管理(小T)线程的对象。一旦(小t)线程启动,它就有自己的生命。
当您将局部变量t
设置为null时,您所做的就是删除对管理(小T)线程的(大T)Thread对象的引用。 (大T)Thread对象不受影响:只要(小t)线程正在运行,它就会继续存在。 (小t)线程不受影响:它将继续做它做的任何事情。将t
设置为null时,唯一的变化就是您不再能够控制新线程。