2013-05-15 2 views
1

Извинения за неоднозначное название - я не мог подумать, как это сделать для названия.Серверное приложение: работает только с выходом println

В принципе, я играю с созданием простых серверных/клиентских программ на Java. Мой сервер запускает поток, чтобы постоянно проверять наличие новых подключений, а затем, если обнаружено соединение, он создает поток и объект соединения только для этого соединения.

Проблема возникает на потоке, который проверяет наличие новых соединений - это не сработало, пока я не начал проверку ошибок и когда я добавил в строке:

System.out.println(""); 

Он вдруг начал работать как надо , Удаление этой строки не приводит к добавлению новых потоков для соединений. Я предположил, что это обеспечило достаточную задержку для правильного запуска потока или чего-то еще, поэтому я некоторое время помещал цикл for, чтобы убедиться, что это сработало - но ничто другое не работало отдельно от одной простой строки.

Вот код для создания новых соединений темы:

class ThreadCreator implements Runnable { 

    ThreadCreator() { 

    } 

    public void run() { 
     while(true) { 
      System.out.println("WHY DOES THIS WORK??"); 
      for(int i = 0; i < connections.size(); i++) { 
       if(connections.get(i).thread == false) { 
        Runnable ReadRunnable = new Read(connections.get(i)); 
        Thread ReadThread = new Thread(ReadRunnable, "MWHAHAH"); 
        ReadThread.setPriority(Thread.MAX_PRIORITY); 
        ReadThread.start(); 
        connections.get(i).thread = true; 
        System.out.println("THREAD CREATED"); 
       } 
      } 
     } 
    } 
} 

Я не могу себе представить, что может быть пойдет не так ..?

+0

Одна из возможностей заключается в том, что без этой линии цикл работает так быстро, что он ест весь доступный процессор. Проверьте, чтобы заменить его 'sleep'. – SJuan76

+0

Ваше право, я добавил в команду сна для потока, и это тоже работает - я не думаю, что это «есть весь процессор» - поскольку он подключается только к одному клиенту –

+0

@KevinWatson, неважно, только один клиент ». Отсутствие оператора 'Thread.sleep()' приведет к тому, что цикл 'while' будет выполняться очень быстро. Попробуйте добавить счетчик внутри цикла 'while', и вы поймете, что я имею в виду. – BLuFeNiX

ответ

1

Одна вещь, чтобы иметь в виду, что System.out.println() почти наверняка предполагает синхронизацию и вызов wait() где-то (так как println() обычно из-промываний и ждет ответа, чтобы быть видимым (или по крайней мере передаются в какой-то другой процесс .) до возвращения

Это может легко «исправить» ваш многопоточную программу, если синхронизация проблема

+0

Включение Thread.currentThread(). sleep (1000), похоже, «работает». Я предполагаю, что это все еще проблема, несмотря на то, что она «работает»? Что это будет означать? –

+0

Трудно сказать, не намного более подробно. Может быть, что какая-то переменная отсутствует «volatile» или у вас отсутствует правильная синхронизация, или вы используете объекты, не связанные с потоком, ... –

+0

Я понятия не имел, что такое изменчивое значение, пока вы не упомянули об этом. Я исследовал его и понял, что два потока (один из которых слушает сообщения, один ищет соединения), оба обращаются к арраисту объектов соединения! Итак, я сделал этот arraylist изменчивой переменной, и это сработало! Я, вероятно, должен исследовать несколько потоков немного больше! –

1

Благодаря Иоахима. - Мне удалось решить эту проблему проблема в том, что нить используется для сравнения! получение сообщений от клиентов и поток, используемый для поиска новых подключений, имел доступ к одной и той же переменной (список соединений).

Я сделал небольшое количество исследований (http://jeremymanson.blogspot.co.uk/2008/11/what-volatile-means-in-java.html) и добавил изменчивый модификатор к переменной - насколько я могу видеть, гарантирует, что любой другой поток с использованием объекта будет уведомлен о том, что он изменился, что позволяет им оба доступа к нему!

Было также упомянуто, что синхронизация потоков важна, переменная изменяется более чем на один поток. Тем не менее, моя переменная читалась одним потоком и менялась другим, так что кажется, что волатильный оператор здесь достаточно!

Большое спасибо!

+0

Вам действительно следует рассмотреть возможность использования классов в пакете java.util.concurrent вместо создания собственных потоков. ThreadPoolExecutor может быть: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html – bobwienholt

Смежные вопросы