0

I'm working on some multithreaded code like this (a lot of details omitted because of relevance):

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

My question is when the program executes for (Consumer c : consumersList) c.start(); in the Producer's constructor, does the consumer threads's run() method immediately gets called? If so what happens when the transactionsQueue is empty -- because the I start to put into transactionsQueue at bank.createTransactionsQueue(filename); which is after the constructor is called (and consumer threads created).

Cœur
  • 37,241
  • 25
  • 195
  • 267
Liumx31
  • 1,190
  • 1
  • 16
  • 33
  • 2
    Google "leaking this in constructor" to find out why it is a bad idea to start threads from inside the constructor of any object. – Solomon Slow Aug 04 '16 at 13:30
  • Are you referring to [this way of starting threads](http://stackoverflow.com/questions/5623285/why-not-to-start-a-thread-in-the-constructor-how-to-terminate)? But I didn't refer to `this`, the way i started my thread? – Liumx31 Aug 05 '16 at 01:30
  • 1
    True. I'm just saying it's a bad habit to start threads inside a constructor. It's not always wrong, but it's wrong often enough that I won't do it in my own code. I don't want some other programmer who's reading my code to have to waste time trying to figure out whether I started the thread safely or not. – Solomon Slow Aug 05 '16 at 13:20

2 Answers2

1

The consumer will block (wait) on transactionsQueue.take() until there is an object in the queue or until the thread is interrupted

Zim-Zam O'Pootertoot
  • 17,888
  • 4
  • 41
  • 69
1

does the consumer threads's run() method immediately gets called

It will get called very shortly after. It's not the next line executed, but will be executed once the new thread actually starts.

If so what happens when the transactionsQueue is empty

The other threads running will be suspended until there is an element in the queue. For each element that gets placed one thread will be awaken to pull the element off the queue.

John Vint
  • 39,695
  • 7
  • 78
  • 108