Java - 如何在1个列表上同步2个线程?

时间:2013-04-30 08:46:05

标签: java multithreading synchronization

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

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

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

我的猜测是

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

线程没有互相调用。它们一直在并发运行。

4 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

一般概念(我在你的案例中看到的)如下:

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

2)编写与thread Athread B相对应的2个类,这两个类都实现Runnable并将List作为构造函数参数。

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)使用与这两个类的实例对应的argumens创建2个线程并启动它们。

答案 2 :(得分:0)

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

final Lock lock = new ReentrantLock(true);

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

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

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

答案 3 :(得分:0)

Reader and writer locks是你的朋友。

  

•线程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之一。在这种情况下,您根本不会写任何通知。阅读器阻止等待新数据。当编写器将数据添加到队列时,读取器将解除阻塞,排出新数据以进行处理,执行其操作然后再次阻塞。