2016-08-04 3 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 пуст, потому что я начинаю с put в transactionsQueue по адресу bank.createTransactionsQueue(filename);, который после вызова конструктора (и создания потребительских потоков).

+2

Google «утечка этого в конструкторе», чтобы выяснить, почему это плохая идея запускать потоки внутри конструктора любого объекта. –

+0

Вы имеете в виду [этот способ создания потоков] (http://stackoverflow.com/questions/5623285/why-not-to-start-a-thread-in-the-constructor-how-to-minminate)? Но я не называл это «тем», как я начал свою нить? – Liumx31

+1

Правда. Я просто говорю, что это плохая привычка начинать темы внутри конструктора. Это не всегда неправильно, но часто бывает неправильно, что я не буду делать это в своем собственном коде. Я не хочу, чтобы какой-то другой программист, который читает мой код, должен тратить время на то, чтобы выяснить, правильно ли я начал тему или нет. –

ответ

1

делает потребитель темы запустим() метод немедленно вызывается

Он будет вызван очень скоро. Это не следующая строка, которая будет выполнена, но будет выполнена, как только начнется новый поток.

Если это так, что происходит, когда transactionsQueue пуст

Другие нити работают, будут приостановлены до тех пор, пока элемент в очереди. Для каждого элемента, который помещается, один поток будет пробуждаться, чтобы вытащить элемент из очереди.

1

Потребитель будет блокировать (ожидание) на transactionsQueue.take(), пока не будет объект в очереди или пока поток прерывается