2013-04-30 28 views
2

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

  • 线程A被追加/变更列表中的项目(写入到列表)
  • 线程B正在显示的项目(仅读出该列表)

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

我的猜测去

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

线程不调用对方。他们一直在同时运行。

+0

你可以显示一点你打算使用的代码吗? – 2013-04-30 08:52:08

+0

为什么不只是同步使用该列表中的数据的方法? – gurvinder372 2013-04-30 08:52:45

+0

重复线程。 请参阅 Qylin 2013-04-30 08:54:49

回答

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(); 

不知道他们是否可以一个接一个地执行,我没有得到通知功能。但是这并不会伤害我的应用程序。

0

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

0

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

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

2)写入对应于您的thread Athread B 2类,都实现Runnable,并采取List作为其构造函数的参数。

3)上列表实例同步这些2类:

// 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个类的实例argumens和启动它们创建2个线程。

+0

这就是我想要做的,但总是以死锁,IllegalMonitoExceptions或非同步执行结束。因为它运作良好,我会与ReentrantLock一起去。 – Bitterblue 2013-04-30 10:11:17

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之一。在这种情况下,你根本不写任何通知。读者阻止等待新数据。当写入者将数据添加到队列中时,读者将取消阻止,排除新数据以处理,执行其操作,然后再次阻止。

+0

有趣。但Q更简单(只是同步读写器)。或者这是否比简单的ReentrantLock有一些好处? – Bitterblue 2014-04-07 07:47:35

+0

@ mini-me,是的,如果你有一个读者和作者不平衡的情况:例如,读者多于作者,写作所花费的时间比阅读或其他例子少。读/写锁中还有额外的逻辑:任意数量的读者对比只有一个作者,如果一个作者请求锁,没有更多的读者等等。 – 2014-04-07 11:46:17