我有一个多线程程序,其中一个线程正在读取数据,而另外一个线程正在处理该数据。如果我有一个写入线程不断添加数据(Example.add()
)而其他读者线程依次读取该数据(Example.getData(1)
,Example.getData(2)
,...),阻止的最佳方法是什么读者,直到他们要求的索引的数据可用?
这个问题有点像生产者 - 消费者,但我不想“消费”数据。
public class Example {
private ArrayList<Integer> data;
public Example() {
data = new ArrayList<Integer>();
}
public int getData(int i) {
// I want to block here until the element
// index i is available.
return data.get(i);
}
public void add(int n) {
data.add(n);
}
}
答案 0 :(得分:1)
您可以在java中使用阻塞队列。当队列为空时,它会阻止队列获取数据,直到消耗完为止。您可以在此处找到有关它的更多信息:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
在线查找Java阻塞队列的一些示例,您可以解决问题
答案 1 :(得分:1)
这似乎是同步线程的合理方法:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html
“条件”链接显示了以下示例:
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
请不要在代码风格上判断我这是条件中示例的直接副本。
在您的情况下,您可能会考虑使用所有线程等待的单个锁定,以便在添加新元素时发出信号。这将导致所有线程被唤醒并测试它们的元素是否存在。如果不是,他们会回去等待下一个信号。
如果你想让他们专门等待1个元素你可以为每个元素保留一个信号,但这似乎有点过分。
类似的东西:
public class Example {
private Lock lock = new ReentrantLock();
private Condition update = lock.newCondition();
public Example(data) {
data = new ArrayList<Integer>();
}
public int getData(int i) {
lock.lock();
try {
while (data.get(i) == null) {
update.await();
}
return data.get(i);
} finally {
lock.unlock();
}
}
public void add(int n) {
data.add(n);
update.signal();
}
}