如何同步 2 个线程来处理列表中的数据?
- 线程 A正在添加/更改列表中的项目(写入列表)
- 线程 B正在显示项目(仅读取列表)
我想在线程 B可以显示列表时“通知”它。在阅读列表时,线程 A不能更改它。当线程 B完成读取时,线程 A可以再次开始更改列表。
我的猜测去
synchronized(obj)
list.wait()
+list.notify()
线程不互相调用。它们始终同时运行。
如何同步 2 个线程来处理列表中的数据?
我想在线程 B可以显示列表时“通知”它。在阅读列表时,线程 A不能更改它。当线程 B完成读取时,线程 A可以再次开始更改列表。
我的猜测去
synchronized(obj)
list.wait()
+list.notify()
线程不互相调用。它们始终同时运行。
一般概念(正如我在您的情况下看到的那样)如下。
1) 创建一个List
您计划使用的实例。
2)编写2个与您对应的类thread A
,thread B
它们都实现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) 使用与这 2 个类的实例对应的参数创建 2 个线程并启动它们。
您可以将所有更改放在 Runnables 中,并将它们放入线程 A 按顺序执行的队列中。在每个作业之后,A 必须生成修改列表的快照并将其提交给线程 B。您可以为此使用 Executors。
阅读器和编写器锁是您的朋友。
•线程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之一。在这种情况下,您根本不写任何通知。阅读器阻塞等待新数据。当写入器将数据添加到队列中时,读取器解除阻塞,排出新数据以进行处理,执行其操作,然后再次阻塞。