我有一个列表,我需要通过两个线程遍历列表。一个从上到下阅读,另一个从下到上阅读。当他们相交时,阅读应停止。
对于迭代列表我可以使用ListIterator,但我无法想到这些线程将如何从同一列表中读取?
答案 0 :(得分:1)
由于线程只是读取,因此不需要使用列表的线程安全版本。
为确保线程在相交时停止读取,您需要同步它们,因此在读取其他项目之前,应检查该项目是否可用。实现这一点的一种简单方法是将当前索引存储在每个线程中,让另一个线程可以访问该索引(确保同步该索引)。这会导致很多开销。
更好的想法是分批工作。将列表分为16个项目。然后线程可以在需要检查交集之前读取整个批处理。
答案 1 :(得分:0)
你可以将一个线程将从0读取到一半的列表分区,第二个将读取半个+ 1到最后一个。
class PrintList implements Runnable{
private List list = new ArrayList();
public PrintList(List list){
this.list = list;
}
@Override
public void run() {
if(Thread.currentThread().getName() != null && Thread.currentThread().getName().equalsIgnoreCase("thread1")){
int mid =list.size()/2;
for(int i = 0; i< mid;i++){
// System.out.println("Thread 1 "+list.get(i));
}
}else if(Thread.currentThread().getName() != null && Thread.currentThread().getName().equalsIgnoreCase("thread2")){
for(int i = mid; i<list.size(); i++){
//System.out.println("Thread 2 "+list.get(i));
}
}
}
}
答案 2 :(得分:0)
如果考虑到线程A处理的总项目和线程B处理的总项目最终将等于列表中的项目数量,则有一种简单的方法可以解决此问题。
因此,如果你有一个计数器,每次线程想要处理下一个元素时递减,你就知道一旦计数器达到零就完成了。
public class MyThreadSyncer {
protected final AtomicInteger elementCount;
public MyThreadSyncer(final Collection c) {
elementCount = new AtomicInteger(c.size());
}
public boolean canProcessNext() {
return (this.elementCount.decrementAndGet() >= 0);
}
}
使用此类,每个线程都设置自己的私有计数器(线程A为0,线程B为大小为1),然后检查如下:
if (this.threadSyncer.canProcessNext()) {
this.theTasks[this.myPosition].process();
this.myPosition += 1; // this line in thread A
this.myPosition -= 1; // this line in thread B
}