如何在没有stop()方法的情况下停止线程?
我有关于Java线程的问题。这是我的场景:如何在没有stop()方法的情况下停止线程?
我有一个线程调用可能需要一段时间的方法。线程保持自己的方法,直到我得到结果。如果我以同样的方式向该方法发送另一个请求,则现在有两个线程正在运行(只要第一个线程没有返回结果)。但我想优先考虑最后一个线程,不想从先前启动的线程获取结果。那么当我没有停止方法时,我怎么能摆脱先前的线程呢?
的标准设计模式是可以被设置为阻止它的线程使用本地变量:
public class MyThread extends Thread {
private volatile boolean running = true;
public void stop() {
running = false;
}
public void run() {
while (running) {
// do your things
}
}
}
这种方式可以greacefully终止线程,也就是未抛出InterruptedException
。
如果* things *在循环中或可以从'run()'方法中断,那么确实会更干净。另外,你可以在'running'中添加一个'volatile'修饰符。 – 2010-07-13 16:44:06
@streetpc:谢谢,确实忘了'volatile'关键字。通常长时间运行的“东西”已经在循环中 - 所以你可以合并循环来考虑运行状态。 – 2010-07-13 16:49:07
小东西;它是布尔,而不是布尔,在Java – 2010-07-13 16:55:07
最好的方法真的取决于该方法的作用。如果它在等待什么,机会是interrupt
将导致你处理并干净退出的InterruptedException。如果它做一些忙,也不会:
class Scratchpad {
public static void main(String[] a) {
Thread t = new Thread(new Runnable() {
public void run() {doWork();}
});
t.start();
try {
Thread.sleep(50);
} catch (InterruptedException ie) {}
t.interrupt();
}
private static void doWork() {
for (long i = 1; i != 0; i *=5);
}
}
在上述情况下,唯一可行的解决方案确实是一个标志变量来打破循环的取消,阿拉@inflagranti早。
事件驱动体系结构的另一种选择是poison-pill:如果你的方法正在等待一个新项目的阻塞队列,那么你可以有一个全局常量项目,称为“毒药”取出的),你杀线程:
try {
while(true) {
SomeType next = queue.take();
if (next == POISON_PILL) {
return;
}
consume(next);
}
} catch //...
编辑:
看起来你真正想要的是一个executor service。当您将作业提交给执行者服务时,您会收到Future
,您可以使用它来跟踪结果并取消作业。
实际上,线程等待twitter的搜索结果,你认为中断会工作吗? – bandit 2010-07-13 17:04:29
如果您只是想减缓其他线程,而不是有它的出口,你可以采取一些其他办法...
一两件事,就像离开你可以去优先变量,当设置时,让你的线程在每次迭代中睡100ms。这会在你的其他线程搜索时有效地阻止它,然后当你重新排列优先级时,它会回到全速。
但是,这是有点马虎。既然你只想要一件事情正在运行,但你希望在优先级完成时记得处理其他事务,那么你可能想用一个重复调用的.process()方法将你的处理放到一个类中。当您希望暂停处理该请求时,您只需停止在该对象上调用.process一段时间。
通过这种方式,你可以实现一堆这样的对象,你的线程只会执行stack.peek()。process();每一次迭代,所以将新的更重要的任务推送到堆栈上会自动停止以前的任何操作。
这导致了更为灵活的调度 - 例如,如果没有任何东西可以让process()返回false,那么您的调度程序可能会转到堆栈中的下一个项目并尝试其“进程()方法,在单线程中给你一些严肃的多任务处理能力,而不会增加资源负担(网络,我猜)
Thread
有一个setPriority(int)
方法。您可以设置第一个线程的优先级是这样的:
Thread t = new Thread(yourRunnable);
t.start();
t.setPriority(Thread.MIN_PRIORITY); // The range goes from 1 to 10, I think
但这不会杀你的线程。如果你只有两个线程使用你的runnable,那么这是一个很好的解决方案。但是,如果您在循环中创建线程,并且始终将最后一个线程的优先级设置为最小,则会获得大量线程。
如果这是应用程序将要执行的操作,请查看ThreadPool
。这不是Java API中的现有类。你将自己创建一个。
ThreadPool是另一个Thread
,它以您想要的方式管理您的所有其他Threads
。您可以设置最大数量的正在运行的线程。在该ThreadPool中,您可以实现一个自动管理线程优先级的系统。例如:您可以让较旧的线程获得更多优先级,以便您可以正确结束它们。
所以,如果你知道如何使用ThreadPool,它可以是非常有趣的。
根据java.lang.Thread
API,您应该使用interrupt()
方法并检查isInterrupted()
标志,而您正在做一些耗时的可取消操作。这种方法可以处理不同种类的“等待情况”:
1.在调用interrupt()
方法
后,wait(),join()和sleep()方法将抛出InterruptedExcetion
2.如果线程被java.nio.channels.Selector
阻塞,它将完成选择器操作
3.如果您在等待I/O线程将接收到ClosedByInterruptException
,但在这种情况下,您的I/O设施必须实现InterruptibleChannel
接口。
如果无法以通用方式中断此操作,则可以简单地放弃上一个线程并从新线程中获取结果。你可以通过java.util.concurrent.Future
和java.util.concurrent.ExecutorService
来完成。
Cosider下面的代码片段:这里
public class RequestService<Result> {
private ExecutorService executor = Executors.newFixedThreadPool(3);
private Future<Result> result;
public Future<Result> doRequest(){
if(result !=null){
result.cancel(true);
}
result = executor.submit(new Callable<Result>() {
public Result call() throws Exception {
// do your long-running service call here
}
});
return result;
}
}
Future
对象代表服务调用的结果。如果再次调用doRequest
方法,它会尝试取消先前的任务,然后尝试提交新的请求。就线程池包含多个线程而言,您不必等到先前的请求被取消。新请求立即提交,方法返回新的请求结果。
我真的不明白,如果你想优先考虑线程或真的停止线程!? – 2010-07-13 16:37:38
不想优先考虑这些。但是2避免以前的所有... – bandit 2010-07-13 21:28:42