当前位置: 首页 > 知识库问答 >
问题:

LinkedBlockingQueue和工作线程-此代码线程安全吗?

郎嘉树
2023-03-14

我试图理解如果下面是线程安全的,它是由另一个开发人员编写的代码,我已经继承和不再与我们在一起。

我有一个BaseProvider类,它实际上是一个消息缓存,由LinkedBlockingQueue表示。该类将传入的消息存储在队列中。

我有一组读此队列的辅助线程。因此,LinkedBlockingQueue是线程安全的。

正如您所注意到的,每个辅助线程都可以访问所有的提供者,所以当一个辅助线程遍历所有提供者并调用getNextQueuedItem()时,当另一个辅助线程也遍历所有提供者并调用getNextQueuedItem()时会发生什么呢?两个工作线程会互相跨过吗?

公共抽象类BaseProvider实现IProvider{

 private LinkedBlockingQueue<CoreMessage> internalQueue = new LinkedBlockingQueue<CoreMessage>();

@Override
public synchronized List<CoreMessage> getNextQueuedItem() {
    List<CoreMessage> arrMessages = new ArrayList<CoreMessage>();                    
    if (internalQueue.size() > 0) {
        Logger.debug("Queue has entries");    
        CoreMessage msg = null;
        try {
            msg = internalQueue.take();
        } catch (InterruptedException e) {
            Logger.warn("Interruption");
            e.printStackTrace();
        }
        if (msg != null) {
            arrMessages.add(msg);
        }
    }
    return arrMessages;
}

protected synchronized void addToQueue(CoreMessage message) {
    try {
        internalQueue.put(message);
    } catch (InterruptedException e) {
        Logger.error("Exception adding message to queue " + message);
    }
}

}

public class Worker implements Runnable 
 @Override
 public void run() {
    Logger.info("Worker - Running Thread : " + Thread.currentThread().getName());

    while (!stopRequested) {
        boolean processedMessage = false;
        for (IProvider provider : providers) {
            List<CoreMessage> messages = provider.getNextQueuedItem();
            if (messages == null || messages.size() != 0) {
                processedMessage = true;
                for (CoreMessage message : messages) {
                    final Message msg = createEndurMessage(provider, message);
                    processMessage(msg);
                    message.commit();
                }
            }
        }
        if (!(processedMessage || stopRequested)) {
            // this is to stop the thread from spinning when there are no messages
            try {
                Thread.sleep(WAIT_INTERVAL);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

}

共有1个答案

司马羽
2023-03-14

如果通过调用AddToQueue向provider类添加了消息,会发生什么?

GetNextQueuedItem()AddToQueue(...)都是Synchronized方法。如果这是访问private...internalqueue的仅有的两个方法,那么多个线程就无法同时访问internalqueue

当一个工作线程遍历所有提供者并调用getNextQueuedItem()时,当另一个工作线程也遍历所有提供者并调用getNextQueuedItem()时会发生什么?

是否询问多个员工访问同一提供商的情况?这不可能发生,因为getNextQueuedItem()synchronized方法。

--或者--

您是否询问不同员工访问不同提供商的情况?这应该无关紧要(至少就baseProvider类而言),因为似乎没有任何方式可以将不同的对象相互连接。

 类似资料:
  • 问题内容: 我在两个不同的线程之间使用。一个线程通过添加数据,而另一个线程通过添加数据。 我的问题是,我是否需要同步对和的访问。是的插入和删除方法是线程安全的? 问题答案: 是。从文档: “ BlockingQueue实现是线程安全的。所有排队方法都使用内部锁或其他形式的并发控制以原子方式实现其效果。但是,除非在实现中另行指定,否则批量Collection操作addAll,containsAll,

  • 问题内容: 我试图用一个例子来说明它的使用和重要性,如果省略的话,它实际上不会给出很好的结果。 但我并不习惯使用。下面的代码的想法是,如果省略则导致无限循环,如果存在则是完全线程安全的。以下代码是线程安全的吗?您是否还有其他使用的现实且简短的代码示例,如果没有该示例,将会给出明显不正确的结果? 这是代码: 问题答案: Victor是对的,您的代码存在问题:原子性和可见性。 这是我的版本: 如果线程

  • 问题内容: 我经常听到对Swing库中缺乏线程安全性的批评。但是,我不确定自己将在自己的代码中执行的操作会导致问题: 在什么情况下,Swing不是线程安全的事实起作用? 我应该积极避免做什么? 问题答案: 切勿执行长时间运行的任务以响应按钮,事件等,因为这些事件在事件线程上。如果您阻止事件线程,则整个GUI将完全无响应,从而使用户感到非常生气。这就是为什么Swing看起来缓慢又硬朗。 使用线程,执

  • 该项目是使用Play framework和Scala语言编写的。我已经实现了编译时依赖关系。我在游戏中遵循了以下示例: https://github.com/playframework/play-scala-compile-di-example 查看MyApplicationLoader。scala: 以及以下代码行: 我的理解是,在第一次调用HomeController时,只创建了一个HomeC

  • 问题内容: 我正在寻找关于线程安全信息和。官方文档(http://docs.python.org/library/urllib2.html和http://docs.python.org/library/httplib.html)缺少有关此主题的任何信息。那里甚至没有提到 线程 一词… 更新 好的,它们不是线程安全的。使它们具有线程安全性需要什么,或者存在使它们具有线程安全性的情况?我问是因为好像

  • 问题内容: 在javadoc中,ConcurrentHashMap如下: 检索操作(包括get)通常不会阻塞,因此可能与更新操作(包括put和remove)重叠。检索反映了自启动以来最新完成的更新操作的结果。对于诸如putAll和clear的聚合操作,并发检索可能仅反映某些条目的插入或删除。同样,迭代器和枚举返回的元素反映了在创建迭代器/枚举时或此后某个时刻哈希表的状态。他们不抛出Concurre