2016-08-12 3 views
1

Прямо сейчас у меня в моей программе есть два потока. Один постоянно пытается прочитать ввод от пользователя, а другие - часы. Тайм-аут возникает, если пользователь не отправляет какие-либо данные за определенный промежуток времени. Два потока выглядеть следующим образом:Должен ли я иметь выделенный поток для просмотра таймаута?

Пользовательский ввод нить

while(true){ 
    if(in.hasNextLine()){ 
     processLine(in.nextLine()); 
     timeLastRecieved = System.currentTimeMillis(); 
    } 
} 

Timeout нить

while(true){ 
    //Check for a timout 
    if(timeLastRecieved+timeoutDuration <= System.currentTimeMillis()) 
     timeUserOut(); 

    else{ 
     //Sleep until it is possible for a timeout to occur 
     Thread.sleep((timeLastSent+timeoutDuration) - System.currentTimeMillis()); 
    } 
} 

В настоящее время я эти нити разделены, но я мог бы объединить их, как это ...

while(true){ 
    if(in.hasNextLine()){ 
     processLine(in.nextLine()); 
     timeLastRecieved = System.currentTimeMillis(); 
    } 

    //Check for a timout 
    if(timeLastRecieved+timeoutDuration <= System.currentTimeMillis()) 
     timeUserOut(); 
} 

Но мне действительно не нужно часто проверять таймаут. Поэтому я должен комбинировать потоки и слишком часто проверять тайм-аут, или мне нужно иметь два потока. Я не так беспокоюсь о производительности, так как я правильно владею этикетом. Если это означает, что продолжительность таймаута составляет примерно 15 минут.

EDIT: Просто хочу указать, что в версии с двумя потоками я сплю, но в комбинированной версии я никогда не сплю нить. Это, очевидно, вызывает оператор if, который проверяет тайм-аут на выполнение более необходимого.

+0

Если поток чтения для опроса пользователя в любом случае может также обрабатывать таймаут. В конце концов, если я правильно вас понимаю, это тайм-аут для ожидания ввода, и, таким образом, потребительский поток (который опросы) будет тем, что время от времени. Единственная причина, по которой я мог бы проверить отдельную проверку потока на тайм-ауты, будет заключаться в том, что обработка пользовательского ввода займет слишком много времени, и если, например, следующий опрос произойдет через 16 минут, а пользователь предоставит ввод после 15: 30 поток опроса, выполняющий оба варианта, может не распознать тайм-аут. – Thomas

+0

Кроме того, вы можете захотеть положить 'timeLastRecieved = System.currentTimeMillis();' перед обработкой ввода, так как в противном случае время, необходимое для обработки, увеличило бы пороговое значение таймаута - что вы могли бы или не захотели бы сделать. – Thomas

+0

хорошая точка @ Томас. Я не должен беспокоиться о длительности обработки, так как она не должна превышать нескольких миллисекунд, а время ожидания - около 15 минут. Корень моего вопроса заключается в том, лучше ли иметь два эффективных потока или один поток, который более часто выполняет оператор if. – user6629259

ответ

0

Суммируя мои комментарии: Я не думаю, что отдельный поток для проверки тайм-аута необходимо.

Причины:

  • Вы должны были бы обмениваться информацией как timeLastRecieved между ними, что может быть более сложным, чем хотелось (например, AFAIK в некоторых случаях доступ к long значений не является атомарной).
  • Из вашего описания кажется, что опрос для ввода и тайм-аута пользователя (без ввода, предоставленного вовремя) тесно связан, поэтому поток опроса также может проверять тайм-аут. Это не значит, что он должен также обрабатывать таймауты, просто сообщая о нем где-нибудь или вызывающий некоторый обработчик тайм-аута, может быть, лучший дизайн.
  • Легче читать и понимать, так как обновление timeLastRecieved и проверка тайм-аута обрабатываются там же.
  • Поскольку между потоком связи и координации не требуется (нет потоков, которые необходимо связывать), это, вероятно, более надежное.

Несколько советов по проверке на тайм-аут:

  • Вы должны рассчитать порог тайм-аута при обновлении timeLastReceived, а затем только проверить Agains текущее время вместо того чтобы вычислять его в каждой итерации.
  • Возможно, вы захотите рассчитать порог таймаута перед обработкой ввода, чтобы он не зависел от времени обработки.

Наконец, существуют альтернативные подходы, такие как использование java.util.Timer. Здесь вы можете просто планировать задачу тайм-аута, которая выполняется, когда должен произойти тайм-аут. Затем эта задача будет проверять, действительно ли тайм-аут произошел, и если он просто не вернется.

Чтобы обработать новый ввод до превышено время ожидания можно было использовать по крайней мере два подхода:

  • Отмена текущего задания тайм-аута, удалите его из таймера и назначить новый.
  • Если запланированная задача тайм-аута уже запланирована, не планируйте новую, а подождите, пока она не будет запущена. Затем текущий проверяет тайм-аут, и если ничего не произошло, он планирует новую задачу (или ее собственную) для текущего ожидаемого таймаута (обратите внимание, что для этого потребуется некоторая межинтерляционная коммутация, поэтому будьте осторожны).
0

У вас должно быть два потока - один ждет данных, поступающих через InputStream/Reader, и тот, который смотрит время, чтобы узнать, прошло ли время, пройденное слишком долго. Единственный способ сделать это с помощью 1 потока - это спящий режим для сегмента периода ожидания, а затем периодически опросить данные. Но это менее эффективно, чем отдельный поток, посвященный чтению из вашего InputStream/Reader.

Вы можете проверить Timeout как общий вариант для реализации таймаут

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