【问题标题】:Synchronizing queue in Java on multiple threads在多个线程上同步Java中的队列
【发布时间】:2014-07-27 22:40:20
【问题描述】:

我了解同步的概念,但我现在确定为什么要这样实现,所以我需要一点帮助:

我有 2 个线程:

PeriodicalThread 将定期接收数据(假设每 5 秒)并将其放入Queue(目前使用ArrayDeque,但我不知道是否有任何其他Queue 实现会更好)

ProccessThread 会不断检查Queue 是否为空。如果不为空,则处理数据(FIFO)

所以,起初我的实现是:

// Both threads are inner class so they have access to Queue

private Queue queue;
private boolean isReadyToProccess;


class PeriodicalThread extends Thread {
    public void run() {
        while(true) {
           if(isNewDataAvailable) {
                // create Data object
                queue.add(data);
           }
        }
    }
}

class ProcessThread extends Thread {
    public void run() {
        while(true) {
           if(!queue.isEmpty() && isReadyToProccess) {
               Data data = queue.poll();
               processData(data);
           }
        }
    }
}

private void processData(Data data) {
    // this method send data over network, and the server response callback
    // changes isReadyToProcess value to true.
}

然后当想要处理同步时,我不知道我是否应该使用lock 对象(以及它是如何实现的)或者是否已经有一个包Queue 实现是线程安全的(因为 add()poll() 方法)

编辑:我忘记了标志isReadyToProcess 指示下一个队列Data 对象是......好吧,准备好进行处理了。这个标志也应该同步。

【问题讨论】:

  • 查看BlockingQueue
  • 布尔标志如何告诉您有关队列中下一个对象的信息?如果队列中有很多对象怎么办?

标签: java multithreading queue


【解决方案1】:

ArrayDeque 不支持并发。相反,使用支持并发工作的真实队列,如BlockingQueue 及其在java.util.concurrent 包中的实现之一。我推荐使用LinkedBlockingQueue

如果您需要在线程之间共享标志,最好使用AtomicBoolean 而不是手动同步原始boolean 字段。

注意:如果您将使用并发进程,最好使用 java.util.concurrent 包提供的类,这些类已经支持开箱即用的锁定和同步。

【讨论】:

    【解决方案2】:

    您正在寻找Blocking Queue 实现

    这提供了您正在寻找的开箱即用的功能。这就是为什么它最适合生产者消费者示例。

    这是一个例子

    public class BlockingQueueExample {
    
        public static void main(String[] args) throws Exception {
    
            BlockingQueue queue = new ArrayBlockingQueue(1024);
    
            Producer producer = new Producer(queue);
            Consumer consumer = new Consumer(queue);
    
            new Thread(producer).start();
            new Thread(consumer).start();
    
            Thread.sleep(4000);
        }
    }
    
    
    public class Producer implements Runnable{
    
        protected BlockingQueue queue = null;
    
        public Producer(BlockingQueue queue) {
            this.queue = queue;
        }
    
        public void run() {
            try {
                queue.put("1");
                Thread.sleep(1000);
                queue.put("2");
                Thread.sleep(1000);
                queue.put("3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    public class Consumer implements Runnable{
    
        protected BlockingQueue queue = null;
    
        public Consumer(BlockingQueue queue) {
            this.queue = queue;
        }
    
        public void run() {
            try {
                System.out.println(queue.take());
                System.out.println(queue.take());
                System.out.println(queue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    【讨论】:

    • 不要使用原始的BlockingQueue
    • @LuiggiMendoza,我不知道 raw BlockingQueue 是什么,但上面的示例使用了 ArrayBlockingQueue。
    【解决方案3】:

    查看 ArrayBlockingQueue 和另一个 BlockingQueue 实现。

    来自文档:

    一个队列,它还支持在检索元素时等待队列变为非空,并在存储元素时等待队列中的空间可用。

    ConcurrentLinkedQueue 也是一个替代方案。

    您可以在此处阅读有关并发队列的更多信息:

    http://docs.oracle.com/javase/tutorial/collections/implementations/queue.html

    【讨论】:

      【解决方案4】:

      在 Java 5 之前,您必须实现等待/通知机制。从 Java 5 开始,您可以使用 BlockingQueue 接口的实现来解决生产者/消费者问题。

      看看这个:

      http://www.javamex.com/tutorials/synchronization_producer_consumer.shtml

      【讨论】:

        【解决方案5】:

        您可以使用 java Blocking Queue 或 Collections.synchronizedList(new LinkedList()),我喜欢 Collections.synchronized... 因为它有效地使您的集合线程安全,并且您不必担心锁和标志等类似问题东西...只是写逻辑可读的代码。

        LinkedList 将为您提供 addFirst() addLast() 以及 getFirst()、getLast() 来实现 FIFO 或 LIFO 行为...

        【讨论】:

          猜你喜欢
          • 2011-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-03
          • 2015-11-03
          • 1970-01-01
          • 2014-06-12
          相关资源
          最近更新 更多