2011-11-08 19 views
2

Javaスレッドに関する基本的な質問をします。プロデューサー - 消費者のシナリオを考えてみましょう。 1人のプロデューサーとn人の消費者がいるとします。コンシューマーはランダムな時間に到着し、配信されると消滅し、各コンシューマーはそれぞれのスレッドで動作します。私はまだ消費者のために永遠の状態を使用する必要がありますか?Java - 基本マルチスレッド

public class Consumer extends Thread { 
    public void run() { 
     while (true) { 
     } 
    } 
} 

このスレッドは永遠に実行されませんか?それは意志

+0

ない私はあなたの質問を理解してください: コードは次のようになります。このスレッドは本当に永遠に実行されます。永遠に続く状態を使用するかどうかは完全にあなた次第です。 – alf

答えて

1

、あなたが

while(beingServed) 
{ 
    //check if the customer is done being served (set beingServed to false) 
} 

のように死ぬためのものだときにループを脱出します。この方法は何かをしたい場合がありますので。

1

なぜ消費者の存在を表すbooleanを使用しないのですか?

public class Consumer extends Thread { 
    private volatile boolean present; 

    public Consumer() { 
     present = true; 
    } 

    public void run() { 
     while (present) { 
      // Do Stuff 
     } 
    } 

    public void consumerLeft() { 
     present = false; 
    } 
} 
+1

現在はvolatileです。 ; –

+0

@PeterLawrey私は何かを忘れていることを知っていた:P –

3

私はスレッドを拡張せず、代わりにRunnableを実装します。

スレッドを永遠に実行したい場合は、永遠にループさせます。

共通の代替が

while(!Thread.currentThread().isInterrupted()) { 

または

while(!Thread.interrupted()) { 
+0

これは、他のスレッド(サービスされていない消費者)が早期に死ぬことを保証するか? –

+0

スレッドを別のスレッドで停止させることは、まさに起こることではありません。実際には簡単ではないことです。あなたは、他のスレッドが死ぬかもしれないと心配する理由を説明できますか? –

+1

嬉しいです。私はその点でJavaとOOPの初心者です。ある時点で5人の消費者がいて、彼らはプロデューサーに奉仕されるのを待っているとします。したがって、明らかに5つのコンシューマスレッドが存在します。 Thread.interrupted()は静的メソッドなので、あるスレッドが割り込みをかけても他のすべてのスレッドも停止することはありませんか? –

0

を使用することですそれは良いアイデアではありませんに(あなたがスレッドの新しい種類をコーディングしている場合を除き - すなわち決して)スレッドを拡張。

最善のアプローチは、このように、スレッドのコンストラクタにRunnableを渡すことです。一般的には

public class Consumer implements Runnable { 

    public void run() { 
     while (true) { 
      // Do something 
     } 
    } 
} 

new Thread(new Consumer()).start(); 

while(true)はOKですが、通常のwakeまたは見せかけの起動のいずれかによって、中断されて処理する必要があります。そこには、Web上に多くの例があります。

Java Concurrency in Practiceを読むことをお勧めします。

+0

目覚めは何ですか?そして、どうやって偽の起床を引き起こしますか?定義上、偽の目覚めはコードによって引き起こされていない起床ですか? –

0

producer-consumerパターンの場合は、wait()とnotify()を使用することをお勧めします。このtutorialを参照してください。 while(true)ループを使用するよりもはるかに効率的です。

+0

BlockingQueueを使用する方がより簡単で簡単です。 –

0

while (true)の中でスレッドを終了するまで(または何らかの方法で強制終了されるまで)スレッドがメッセージを処理するようにするには、プロデューサスレッド(またはSynchronizedQueue、またはキューシステム)への同期呼び出しがあります。メッセージが利用可能になります。メッセージが消費されると、ループが再開して再び待機します。

メッセージをプロデューサからプルするスレッドを手作業でインスタンシエートしたい場合は、while (true)を使用しないでください。

1

最初に、消費者ごとに作成することができ、消費者が仕事を終えると、消費者は実行機能を終了して死んでしまうため、無限ループは必要ありません。しかし、消費者ごとにスレッドを作成することは、スレッドの作成がパフォーマンスの点で非常に高価なので、良い考えではありません。スレッドは非常に高価なリソースです。加えて、私はrunnableを実装し、スレッドを拡張しない方が良いという上記の答えに同意します。あなたのスレッドをカスタマイズしたいときにだけスレッドを拡張してください。 スレッドプールを使用することを強くお勧めします。消費者はスレッドプール内のスレッドによって実行された実行可能オブジェクトになります。

public class ConsumerMgr{ 

int poolSize = 2; 

int maxPoolSize = 2; 

long keepAliveTime = 10; 

ThreadPoolExecutor threadPool = null; 

final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(
     5); 

public ConsumerMgr() 
{ 
    threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize, 
      keepAliveTime, TimeUnit.SECONDS, queue); 

} 

public void runTask(Runnable task) 
{ 
    // System.out.println("Task count.."+threadPool.getTaskCount()); 
    // System.out.println("Queue Size before assigning the 
    // task.."+queue.size()); 
    threadPool.execute(task); 
    // System.out.println("Queue Size after assigning the 
    // task.."+queue.size()); 
    // System.out.println("Pool Size after assigning the 
    // task.."+threadPool.getActiveCount()); 
    // System.out.println("Task count.."+threadPool.getTaskCount()); 
    System.out.println("Task count.." + queue.size()); 

}