关于blockqueue和多线程消费者的一些困惑

时间:2016-08-04 10:00:24

标签: java multithreading producer-consumer

我正在处理一些像这样的多线程代码(由于相关性而忽略了很多细节):

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开始transactionsQueuebank.createTransactionsQueue(filename);,这是在调用构造函数之后(并创建了消费者线程)

2 个答案:

答案 0 :(得分:1)

消费者将阻塞(等待)transactionsQueue.take(),直到队列中有对象或线程被中断为止

答案 1 :(得分:1)

  

消费者线程的run()方法是否立即被调用

很快就会被召唤。它不是下一行执行的,但会在新线程实际启动后执行。

  

如果是这样,当transactionQueue为空时会发生什么

其他运行的线程将被暂停,直到队列中有一个元素。对于放置的每个元素,将唤醒一个线程以将该元素从队列中拉出。