两个线程读取相同的列表但来自不同的目的

时间:2017-07-12 09:19:29

标签: java multithreading listiterator

我有一个列表,我需要通过两个线程遍历列表。一个从上到下阅读,另一个从下到上阅读。当他们相交时,阅读应停止。

对于迭代列表我可以使用ListIterator,但我无法想到这些线程将如何从同一列表中读取?

3 个答案:

答案 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
}