2010-04-14 84 views
4

我有一个线程使用不同的代理从互联网下载一些图像。 有时会挂起,不能以任何方式杀死。我只是不能杀死Java线程

public HttpURLConnection uc; 
public InputStream in; 

Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("server", 8080)); 
URL url = new URL("http://images.com/image.jpg"); 
uc = (HttpURLConnection)url.openConnection(proxy); 
uc.setConnectTimeout(30000); 
uc.setAllowUserInteraction(false); 
uc.setDoOutput(true); 
uc.addRequestProperty("User-Agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"); 
uc.connect(); 

in = uc.getInputStream(); 

当它挂起时,它冻结在uc.getInputStream()方法。 我做了一个计时器,试图杀死线程,如果它的运行时间超过3分钟。 我试过.terminate()这个线程。没有效果。 我试图从主线程uc.disconnect()。该方法也挂起,并与它,主线程。我试过in.close()。没有效果。 我试过uc=nullin=null希望能够结束线程的异常。它继续运行。 它永远不会通过uc.getInputStream()方法。

在我上一次测试中,线程在接收到所有上述命令(或各种组合)后持续了14个小时。我必须杀死Java进程才能停止线程。

如果我只是忽略该线程,并将其实例设置为null,则该线程不会死亡并且不会被垃圾收集器清理。我知道,因为如果让应用程序运行好几天,Java进程会占用越来越多的系统内存。在3天内,我的8Gb系统RAM占用了10%。

无论如何杀死一个线程是不可能的?

+2

在打开调试器时,你必须在你的脖子上戴上一些大蒜,在周围撒上圣水,然后在过程的心脏中捣碎一块木制牛排,最后切断它的头部并烧掉剩余物。这是确定的唯一方法。 (或者当然是将它从轨道上剔除) – 2010-04-14 14:32:58

+1

@Jeffrey L Whitledge:是的,这样做,然后你发现自己有二十多个线程在僵局中冻结,因为刚刚杀死的线程在按住钥匙的时候被焚烧没有人可以释放,因为对象处于不一致的状态。 – 2010-04-15 02:59:09

回答

3

尝试设置uc.setReadTimeout(30000);

+0

它的工作原理。谢谢。 – Adrian 2010-04-15 11:21:04

4

这是不可能杀死一个线程什么?

在很多情况下,是的 - 特别是当线程在不可中断的IO上被阻塞时。 您可能可以通过从另一个线程呼叫uc.getInputStream().close()来解锁它。虽然这可能不是线程安全的。 HttpUrlConnection也有一个setReadTimeout(),你应该设置你的情况。

0

不,你不能。从外部杀死线程本身就是一种不安全的操作。

你可以做的是让线程自动关闭自己。编写下载线程,以便在超时超时时自行终止。

+0

我想这样做,但线程挂在一个API函数。我在线程冻结后没有任何控制(我不能说“do {} while(alive == true)”,并且只要我想设置alive = false,因为while线由于API方法冻结而永远不会执行) 。 – Adrian 2010-04-14 12:44:15

4

除了设置读取超时(在其他回复中提到)之外,您是否尝试中断线程?

+0

好的建议;它会从任何地方卡住java.io.InterruptedIOException,并将getInputStream记录为可以抛出这种东西。 (好吧,它是一个超类。) – 2010-04-14 14:32:16