2016-08-04 8 views
0

のBlockingQueueとマルチスレッドの消費者に関するいくつかの混乱:私はこのようないくつかのマルチスレッドコード(理由は関連性を省略多くの詳細)に取り組んでいます

public class Producer { 

    private static BlockingQueue<Transaction> transactionsQueue = new LinkedBlockingQueue<Transaction>(); 
    private static ArrayList<C> consumersList = new ArrayList<C>(); 

    public Producer(int a, int b) { 
     for (int i = 0; i < a; i++) 
      accountsList.add(new Account(i, DEFAULT_BALANCE)); 

     for (int i = 0; i < b; i++) 
      consumersList.add(new Consumer()); 

     for (Consumer c : consumersList) 
      c.start(); //question line of code 
    } 


    public class Consumer extends Thread{ 
     @Override 
     public void run(){ 
      while (true) { 
       try { 
        Transaction nextTransaction = transactionsQueue.take(); 

        if(nextTransaction.equals(FINAL_TRANSACTION)) 
         break; 

        Account acc = accountsList.get(nextTransaction.getTo()); 
        acc.makeTransaction(nextTransaction); 
        System.out.println(acc); 

       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 

    public static void main(String []args){ 
     try{ 
      launch(args[0], NUM_OF_ACCOUNTS, Integer.parseInt(args[1])); 
     }catch (Exception e){ 
      System.out.println("Incorrect args. Starting with default arguments"); 
      launch(SMALL_FILE, NUM_OF_ACCOUNTS, NUM_OF_THREADS); 
     } 
    } 

    private static void launch(String filename, int numOfAccounts, int numOfConsumers) { 
     Producer bank = new Producer(numOfAccounts, numOfConsumers); 
     bank.createTransactionsQueue(filename); //start putting into transactionsQueue 
     bank.close(); 
    } 
} 

私の質問は、プログラムがでfor (Consumer c : consumersList) c.start();を実行しますProducerのコンストラクタでは、コンシューマスレッドのrun()メソッドがすぐに呼び出されますか?もしそうなら、私はtransactionsQueueが空であるときに何が起こるのですか?をtransactionsQueueに入れてbank.createTransactionsQueue(filename);になります。コンストラクタが呼び出された後にコンシューマスレッドが作成されます。

+2

Googleが「コンストラクタでこれを漏らしている」という理由で、オブジェクトのコンストラクタ内からスレッドを開始するのが悪い考えを知りました。 –

+0

あなたは[このスレッドを開始する方法](http://stackoverflow.com/questions/5623285/why-not-to-start-a-thread-in-the-constructor-how-to-terminate)を参照していますか?しかし、私は「this」を参照していない、私のスレッドを開始する方法? – Liumx31

+1

真。私は、コンストラクタ内でスレッドを開始するのは悪い習慣だと言っているだけです。それはいつも間違っているわけではありませんが、それは私自身のコードではしばしば間違っています。私はコードを読んでいる他のプログラマーがスレッドを安全に開始したかどうかを判断しようと時間を無駄にしないようにしたい。 –

答えて

1

を中断された消費者スレッドのrun()メソッドは、直ちに

呼び出しませんそれは非常に直後に呼び出されます。次の行は実行されませんが、実際に新しいスレッドが開始されると実行されます。

transactionsQueueは、キュー内の要素があるまで実行されている他のスレッドが中断されます

空であるときに何が起こる場合。配置された各要素に対して、1つのスレッドが目覚めて要素をキューから引き出します。

1

オブジェクトがキューにまたはスレッドまでがあるまで、消費者がtransactionsQueue.take()に(待機)をブロックしますが

関連する問題