背景线程复制集合并重新初始化原始,可能吗?

时间:2012-04-04 13:52:23

标签: java multithreading concurrency

说我有课:

public class Chat {
  private volatile ConcurrentLinkedQueue messages = new ConcurrentLinkedQueue();

  // getter/setter for messages queue
}

我有一个后台线程,它将此类的一个实例作为参数:

Thread t = new Thread(new QueuePersister(messages));
t.start();

线程的任务是:

public class QueuePersister implements Runnable {
   private volatile ConcurrentLinkedQueue messages = new ConcurrentLinkedQueue(); 

   public QueuePersister(ConcurrentLinkedQueue messages) {
     this.messages = messages;
   }

   @Override
    public void run() {
        while(true) {

            // this is a 2 step process, probably should synchronize?? i.e. copy and re-initializing
            ConcurrentLinkedQueue copy = messages;
            messages = new ConcurrentLinkedQueue();

            // save to disk using the copy queue


            // sleep for x seconds
         }
    }
}

我想要做的是:

我的消息被保存到队列中,并且后台线程每x秒创建一个队列副本,重新设置原始消息队列,以便在旧副本持久保存到文件/ db时可以开始获取新数据。

这样任何未来的写入都将对新队列进行。

在我的测试中,这不起作用,因为我似乎无法重新初始化传递给线程的队列。

我认为这是因为消息队列是通过引用传入的,但它传递了引用的副本,并且不允许更改引用。您可以更改所引用的对象,但不能更改引用。

如果这是真的,那么我还有什么选择呢?我可以在课堂上公开一些方法来为我做这个吗?

注意:当我的应用程序运行时,Chat对象只创建一次。

多个线程将访问Chat对象。

更新

只有一个线程可以执行此“持久性”,我希望它能够在Chat.messages队列中工作。我想要它做的只是制作一个集合的副本,并重新设置聊天的集合,然后它可以花时间将复制的队列版本保存到磁盘。

2 个答案:

答案 0 :(得分:3)

因此,messages类中您的帖子中的messagesChat不同吗?所以当你这样做时:

   ConcurrentLinkedQueue copy = messages;
   messages = new ConcurrentLinkedQueue();

这只影响Thread集合字段。您不需要volatile也不需要并发。

我怀疑你要做的是在线程中使用集合。由于您使用的是ConcurrentLinkedQueue,因此您可以从其他线程对队列进行操作,而无需进行复制和替换舞蹈。当其他线程添加到队列时,您可以安全地从队列中删除项目。这就是并发类的全部目的。

您应该将messages中的Chat字段标记为private final而不是易变的,因为它不需要更改。您也可以在Thread内将其标记为最终。

答案 1 :(得分:1)

我会考虑改用LinkedBlockingQueue。它有一个drainTo方法,可以将队列内容清空到另一个队列。此时,您可以将LinkedBlockingQueue声明为final。

的Javadoc

  

public int drainTo(Collection c)

     

从此队列中删除所有可用元素并将其添加到   给予收集。该操作可能比重复操作更有效   轮询此队列。尝试添加时遇到故障   集合c的元素可能导致元素不在,   抛出关联异常时的一个或两个集合。   尝试将队列排到自身导致   IllegalArgumentException异常。此外,该操作的行为是   如果在操作时修改了指定的集合,则为undefined   正在进行中。