Поток Java.сон протекает нитями?
Итак, я унаследовал немного кода, который ожидает связи из сетевого источника.
Пока он ждет дополнительных данных из сетевого сокета, вызывается Thread.sleep(10)
. Это, по-видимому, вызывает утечку потока, о чем сообщают jconsole и My thread dump здесь (есть сотни записей для Thread-68, Thread-385 и т. д... но я сократил для краткости):
Wed Jan 18 09:14:40 PST 2012
2012-01-18 09:14:50
Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.0-b11 mixed mode):
"Thread-69" daemon prio=10 tid=0x00007f01a047c800 nid=0x3725 waiting on condition [0x00007f019eaf4000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.unitt.framework.websocket.simple.NetworkSocket.run(NetworkSocket.java:304)
at java.lang.Thread.run(Thread.java:662)
"Thread-68" daemon prio=10 tid=0x00007f01a0500000 nid=0x371c waiting on condition [0x00007f019ecf6000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.unitt.framework.websocket.simple.NetworkSocket.run(NetworkSocket.java:304)
at java.lang.Thread.run(Thread.java:662)
Рассматриваемый код:
public class NetworkSocket implements NetworkSocketFacade, Runnable
{
... removed many irrelevant methods
public void run()
{
byte[] readBuffer = new byte[512 * 1024];
while (isRunning)
{
//ioLogger.debug("in while(isRunning) loop");
try
{
int length = input.available();
if (length > 0)
{
int read = input.read(readBuffer, 0, readBuffer.length);
if (read < 0)
{
isRunning = false;
//@todo: do we disconnect?
ioLogger.debug("setting isRunning FALSE after read < 0");
}
else
{
//read data and process
}
}
else
{
//ioLogger.debug("nothing to read, sleeping");
try
{
Thread.sleep( 10 );
}
catch ( InterruptedException e )
{
//do nothing, keep going
}
}
}
// some catch blocks and logging after this
У меня есть некоторые опасения, что вызов сна с такой частотой может вызвать проблемы, и я попытался увеличить время сна с 10 до 250, просто чтобы смягчить ситуацию. Это несколько улучшает ситуацию,но со временем я все еще сталкиваюсь с той же проблемой-я постоянно пропускаю потоки, пока не выхожу из пространства кучи.
Есть ли у кого-нибудь идеи по поводу такого поведения? Я бы не подумал, что что-то столь фундаментальное, как Thread.sleep()
, может вызвать такие проблемы.
4 ответа:
Проблема не в
Thread.sleep()
, а в логике потока.Из кода, который вы опубликовали, поток завершится, когда
Кажется, что нет такого состояния мира, когда это было бы так.isRunning = false
. Теперь единственный способ дляisRunning
установить значениеfalse
- это когдаinput.available()
возвращает положительное значение, а затемinput.read()
возвращает отрицательное значение.В результате все потоки, использующие этот метод
P.S. Это основано на коде, который вы опубликовали. Если есть способы дляrun()
, будут жить так долго, как живет процесс., большую часть времени они проводят вThread.sleep()
.isRunning
установить значениеfalse
, которые вы в данный момент не показываете, обновите свой вопрос.
Thread.sleep()
это точно не проблема. Он не создает никаких потоков или чего-то подобного.Я могу только догадываться, что
isRunning
никогда не устанавливается (или изменение не видно из-за плохой синхронизации), и новые потоки создаются, в то время как старые все еще работают.Кстати, вместо того, чтобы постоянно вызывать
available
и спать, поток может просто блокироватьinput.read()
. Код был бы намного проще и более отзывчивым.
Thread.sleep()
ничего не" виляет " и не может быть учтено при поиске утечки потока...Вы должны искать то, что производит эти потоки. Какая часть кода отвечает за создание новых потоков в вашем приложении ? На этот вопрос вам придется ответить в первую очередь
Распространенная ошибка состоит в том, чтобы забыть сделать
isRunning
логическоеvolatile
Без этого ключевого слова вы можете изменить его в одном потоке, и нет никакой гарантии, что другой поток увидит это изменение. Таким образом, вы можете установитьisRunning
в false, но поток продолжает работать.Чтобы решить эту проблему, я бы упростил код даматически, чтобы он вращался вокруг переменной, подобной этой. частная летучих логическое закрыт = ложь; частная окончательной входного потока;
public void close() throws IOException { closed = true; input.close(); } public void run() { byte[] readBuffer = new byte[512 * 1024]; try { // you wouldn't keep looping after an exception. int len; while ((len = input.read(readBuffer)) > 0) { //read data and process } } catch (IOException ioe) { if (!closed) // log unexpected exception } }
Чем проще вы сделайте это, тем более вероятно, что это сработает. ;)