2

如何同步 2 个线程来处理列表中的数据?

  • 线程 A正在添加/更改列表中的项目(写入列表)
  • 线程 B正在显示项目(仅读取列表)

我想在线程 B可以显示列表时“通知”它。在阅读列表时,线程 A不能更改它。当线程 B完成读取时,线程 A可以再次开始更改列表。

我的猜测去

  • synchronized(obj)
  • list.wait()+list.notify()

线程不互相调用。它们始终同时运行。

4

4 回答 4

0

一般概念(正如我在您的情况下看到的那样)如下。

1) 创建一个List您计划使用的实例。

2)编写2个与您对应的类thread Athread B它们都实现RunnableList作为它们的构造函数参数。

3)在列表实例上同步这两个类:

// method in class that adds
public void add() {
  synchronized(list) {
    // perform addition ...
    list.notify();
  }
}

// method in class that reads
public void read() throws InterruptedException {
  synchronized(list) {
    while (list.isEmpty())
      list.wait();
    // process data ...
  }
}

4) 使用与这 2 个类的实例对应的参数创建 2 个线程并启动它们。

于 2013-04-30T09:19:57.193 回答
0

我尝试了此处此处建议的并发包,效果很好。线程相互锁定:

final Lock lock = new ReentrantLock(true);

// thread A
lock.lock();
// write to list
lock.unlock();

// thread B
lock.lock();
// read from list
lock.unlock();

不确定他们是否可以一个接一个地精确执行,我没有得到通知功能。但这不会影响我的申请。

于 2013-04-30T10:08:29.393 回答
0

您可以将所有更改放在 Runnables 中,并将它们放入线程 A 按顺序执行的队列中。在每个作业之后,A 必须生成修改列表的快照并将其提交给线程 B。您可以为此使用 Executors。

于 2013-04-30T08:52:43.463 回答
0

阅读器和编写器锁是您的朋友。

•线程A正在添加/更改列表中的项目(写入列表)

...所以它可以使用写锁...

•线程 B 正在显示项目(仅读取列表)

...所以它可以使用读锁。

让我们假设您正在使用一些直接的东西来等待/通知(例如,内置的Object方法)来阻止读取和显示线程。此时,您的代码如下所示:

/** This is the read/write lock that both threads can see */
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

/** This method is called by thread A (the writer / modifier) */
public void add() {
    try {
        // Only one writer at a time allowed
        lock.writeLock().lock();
        // Insert code here: Add to the list 
    } finally {
        // Unlock in the finally block to ensure that lock is released
        lock.writeLock().unlock();
    }
    // Notify anyone who's waiting for data
    list.notify();
}

/** This method is called by thread B (the reader / displayer) */
public void read() throws InterruptedException {
    try {
        // As many readers as you like at a time
        lock.readLock().lock();
        // Insert code here: read from the list
    } finally {
        // Unlock in the finally block to ensure that lock is released
        lock.readLock().unlock();
    }
    // Wait for new data
    list.wait();
}

为了使事情更方便,您可以通过使用阻塞数据结构来摆脱通知/等待消息:例如BlockingQueues之一。在这种情况下,您根本不写任何通知。阅读器阻塞等待新数据。当写入器将数据添加到队列中时,读取器解除阻塞,排出新数据以进行处理,执行其操作,然后再次阻塞。

于 2014-04-04T12:41:55.643 回答