3

メールをキューに入れ、後でコンシューマスレッドが消費するメールユーティリティを作成しようとしています。プロデューサコンシューマパターンの実装

私は典型的なプロデューサ - コンシューマパターンを実装しようとしていますが、何かがうまくいきません。

私は骨格を書きましたが、骨格は期待どおりに機能していません。

MailProducer.java

public class MailProducer implements Callable<Void> 
{ 

@Override 
public Void call() throws Exception 
{ 
    System.out.println("inside mail Producer"); 
    System.out.println("Thread executing = " + 
          Thread.currentThread().getName()); 
    return null; 
} 

} 

public class MailConsumer implements Callable<Void> 
{ 

@Override 
public Void call() throws Exception 
{ 
    System.out.println("inside mail consumer"); 
    System.out.println("Thread executing = " + 
         Thread.currentThread().getName()); 
    return null; 
} 

} 

MailConsumer.java、最終的にはエグゼキュータ

MailExecutor.java

私はプログラムを実行すると
public class MailExecutor 
    { 

private static final int NTHREADS = 25; 
private static final ExecutorService exec = 
       Executors.newFixedThreadPool(NTHREADS); 

public static void main(String[] args) 
{ 
    exec.submit(new MailConsumer()); 
    exec.submit(new MailProducer()); 

    System.out.println("inside main"); 

} 

    } 

は今、は、私はそれがそれぞれのクラスで書かれているものを印刷しておくために、前後に生産者と消費者を行くことを期待しています。しかし、代わりに、プログラムは、以下の行を印刷した後に何もしません。何がうまくいかないのですか?何か不足していますか?

出力 ...(出力が間違って起こっている。私が予想していたものではない?)一回の実行のためのRunnableまたは呼び出し可能

inside mail consumer 
    inside main 
    Thread executing = pool-1-thread-1 
    inside mail Producer 
    Thread executing = pool-1-thread-2 

答えて

2

共有キューがありません。キューなしでは、あなたは何も持っていません。

生産者が作業をキューに入れます。消費者は作業をキューから取り除く。 BlockingQueueを使用してください。put()take()の方法は、ブロックコールです。別々のスレッドでプロデューサとコンシューマを実行すると、これらのメソッドを呼び出すときに安全にブロックすることができます。

プロデューサもコンシューマもCallableである必要はありません。 Runnableとなります。 Executorを使ってすべてを結びつけるのは良い考えです。

+0

大したことではありませんが、ブロックメソッドは実際にput()とtake()です。スペースがない場合、falseはfalseを返します。 – devo

+0

@ user529734非常にそう! thx - 訂正されました。 – Bohemian

1

ExecutorService.submitスケジュール。あなたの出力は、MailProducerとMailConsumerの両方が一度実行されることを示しています。

あなたはループであなたの生産と消費者法の内部を置く必要があります。

import java.util.concurrent.*; 

public class Executor { 

    private static final int NTHREADS = 25; 
    private static final ExecutorService exec = 
     Executors.newFixedThreadPool(NTHREADS); 


    public static void main(String[] args) { 
     exec.submit(new MailConsumer()); 
     exec.submit(new MailProducer()); 

     System.out.println("inside main"); 
    } 


    static class MailProducer implements Runnable { 
     @Override 
     public void run() { 
      while (true) { 
       System.out.println("inside mail Producer"); 
       System.out.println("Thread executing = " + 
         Thread.currentThread().getName()); 
      } 
     } 
    } 

    static class MailConsumer implements Runnable { 
     @Override 
     public void run() { 
      while (true) { 
       System.out.println("inside mail Consumer"); 
       System.out.println("Thread executing = " + 
         Thread.currentThread().getName()); 
      } 
     } 
    } 
} 

これは、あなたが期待する出力を提供します。

+0

あなたの答えが重要な問題を修正している間に、主な点が欠落しています:「BlockingQueue」などの使用。 – michael667

+0

はい、元のポスターのコードもそうです。彼はスケルトンとして記述していましたので、私は彼がThreadPoolの作業を最初に行い、後でProducent-Consumerを実装しようと考えていました。 – socha23

+0

はい、これはちょうど2つのスレッドを使用するため、エグゼキュータは必要ありません。 –

0
  1. プロデューサ/コンシューマコードが複数回実行されるようにループを使用する必要があります。

  2. あなたのスレッドは互いに通信しません。現在、実行中のスレッドは2つだけです。それを行う方法のBlockingQueue javadocの例を見てください。