2016-08-12 6 views
1

今私は自分のプログラムで2つのスレッドを実行しています。常にユーザーからの入力を読み取ろうとし、もう一方はタイムアウトを監視します。ユーザーが一定の時間内に入力を送信しない場合、タイムアウトが発生します。 2つのスレッドは次のようになります。タイムアウトを監視する専用のスレッドが必要ですか?

ユーザ入力スレッド

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

タイムアウトスレッド

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(); 
} 

しかし、実際には頻繁にタイムアウトを確認する必要はありません。スレッドを結合してタイムアウトを頻繁にチェックするか、2つのスレッドを用意する必要があります。私は適切なコーディングエチケットであるので、パフォーマンスについて心配していません。それが何かを意味するならば、15分のようなものでタイムアウト期間。

EDIT:2つのスレッドを持つバージョンでは私は眠っていますが、結合バージョンではスレッドをスリープ状態にはしません。これは明らかにタイムアウトが必要以上に実行されるかどうかをチェックするif文を引き起こします。

+0

読み取りスレッドがユーザー入力をポーリングすると、タイムアウトも処理できます。結局のところ、私が正しくあなたを理解していれば、それは入力を待つためのタイムアウトなので、消費者スレッド(世論調査)はとにかく時間切れになるでしょう。私は、ユーザー入力の処理に時間がかかり、たとえば次のポーリングが16分後に発生し、ユーザーが15分後に入力を提供した場合、 30両方を行うポーリングスレッドがタイムアウトを認識しないことがあります。 – Thomas

+0

また、入力を処理する前に 'timeLastRecieved = System.currentTimeMillis();'を置くことを検討すると、処理に必要な時間がタイムアウトのしきい値を増加させます。 – Thomas

+0

良い点@トーマス。タイムアウトは約15分に設定されていますが、処理の長さは数ミリ秒を超えてはならないので、私は心配していません。私の質問の根源は、2つの効率的なスレッドを持つ方が良いかどうか、あるいはif文を実行するスレッドがより頻繁に必要な場合です。 – user6629259

答えて

0

を実装するための一般的なオプションとしてTimeoutをチェックアウトすることができます:私はタイムアウトをチェックするための別のスレッドが必要だとは思いません。

理由:

  • あなたが(例えば私の知る限り、いくつかのケースでlong値へのアクセスがアトミックではありません)望んでいた以上に複雑になる可能性があり、それらの間のtimeLastRecievedなどの情報を共有する必要があると思います。
  • あなたの説明から、ユーザー入力とタイムアウト(入力が時間通りに提供されていない)のポーリングは密接に関連しているようで、ポーリングスレッドはタイムアウトもチェックできます。つまり、タイムアウトを処理しなければならないというわけではありません。ちょうどそれをどこかに報告するか、タイムアウトハンドラを呼び出す方が優れた設計になるかもしれません。
  • timeLastRecievedの更新とタイムアウトのチェックが同じ場所で処理されるため、読みやすく理解しやすくなります。
  • スレッド間通信やコーディネーションは必要ありません(通信が必要なスレッドはありません)ので、おそらくより堅牢です。タイムアウトのチェックに

いくつかのヒントは:

  • あなたはtimeLastReceivedを更新するときにタイムアウトしきい値を計算して、唯一の反復ごとに、それを計算するのではなく、現在の時間againsチェックする必要があります。
  • 入力を処理する前にタイムアウトのしきい値を計算して、処理時間にも依存しないようにすることができます。

最後に、java.util.Timerのような別のアプローチがあります。ここでは、タイムアウトが発生したときに実行されるタイムアウトタスクをスケジュールすることができます。そのタスクは、実際にタイムアウトが発生したかどうかをチェックし、タイムアウトが戻っていないかどうかを確認します。 、現在のタイムアウトのタスクをキャンセルタイマーからそれを削除し、新しいものをスケジュール

  • :タイムアウトは、あなたは、少なくとも2つのアプローチを使用することができます発生した前に、新しい入力を処理するために

  • すでにスケジュールされたタイムアウトタスクがある場合は、新しいタスクをスケジュールしないで、現在のタスクが実行されるのを待ちます。現在のものがタイムアウトをチェックし、何も起こらなければ、現在の予想されるタイムアウトのために新しいタスク(またはそれ自体)をスケジュールします(これにはスレッド間通信が必要なので注意してください)。
0

2つのスレッドが必要です.1つはInputStream/Readerからのデータの受け取りを待機し、もう1つは経過時間が長すぎるかどうかを確認する時間です。 1つのスレッドでそれを行う唯一の方法は、タイムアウト期間のセグメントに対してスリープ状態にしてから、定期的にデータをポーリングすることです。しかし、それはあなたのInputStream/Readerからの読み取り専用のスレッドを持つよりも効率が悪いです。

あなたは私のコメントを要約すると、タイムアウト

関連する問題