Я просто не могу убить поток Java - PullRequest
4 голосов
/ 14 апреля 2010

У меня есть ветка, которая скачивает некоторые изображения из интернета, используя разные прокси. Иногда он зависает и не может быть убит никаким способом.

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=null, in=null в надежде на исключение, которое завершит поток. Он продолжает работать. Он никогда не проходит метод uc.getInputStream().

В моем последнем тесте поток длился более 14 часов после получения всех вышеперечисленных команд (или различных комбинаций). Мне пришлось убить процесс Java, чтобы остановить поток.

Если я просто игнорирую поток и устанавливаю его экземпляр равным нулю, поток не умирает и не очищается сборщиком мусора. Я знаю это, потому что если я позволю приложению работать в течение нескольких дней, процесс Java отнимает все больше системной памяти. За 3 дня это заняло 10% моей оперативной памяти 8 ГБ.

Невозможно что-нить убить?

Ответы [ 4 ]

5 голосов
/ 14 апреля 2010

Нить невозможно что-то убить?

Во многих случаях да - особенно когда поток заблокирован на непрерывном вводе-выводе. Вы можете разблокировать его, вызвав uc.getInputStream().close() из другого потока. Хотя это не может быть потокобезопасным. HttpUrlConnection также имеет setReadTimeout (), который вы, вероятно, должны установить в вашем случае.

4 голосов
/ 14 апреля 2010

Наряду с установкой таймаута чтения (упомянутого в других ответах), вы пытались прервать поток?

4 голосов
/ 14 апреля 2010

Попробуйте установить uc.setReadTimeout(30000);

0 голосов
/ 14 апреля 2010

Нет, ты не можешь. Уничтожение потока извне - небезопасная операция.

То, что вы можете сделать, это заставить Нить добровольно закрыться. Напишите поток загрузки так, чтобы он прекратил себя, когда превышено время ожидания.

...