添加到ArrayList时索引超出范围

时间:2018-03-22 12:29:14

标签: java arraylist sieve

编辑:只是要指出,我知道哪些索引超出界限通常意味着 - 如果它不是以前从未遇到过的东西,我就不会发布这个帖子,在这种情况下是一个数组 list 拒绝添加6000左右的普通旧int,以及一个大小为2mil的字节数组......

解决方案:对于其他寻找此答案的人来说,这是由于多个线程同时添加到列表中,导致它无法正确更新列表的新大小。要避免它,您需要同步添加到列表中的部分,或者使用类似Vector的部分。

我有一个程序,用于查找低于给定数字n(Eratosthenes Sieve)的素数,我已经并行化了。在其中,我已经在字节数组中标记了所有非素数的数字,并且我有一个包含我找到的素数的ArrayList。

最初,我只是添加数字直到sqrt(n),并标记我发现的素数的所有产品(所以如果我找到5,我标记:5 * 5和5 * 5 + 2 * 5,和5 * 5 + 3 * 5等),这样当我找到所有素数达到n的平方根时,我已经划掉了所有在sqrt(n)之间不是素数的数字直到n。

此时,我所要做的就是遍历字节数组的其余部分,并检查它是否标记为素数,如果是,则添加它。但是,我在将素数作为素数添加到素数的ArrayList的部分获得了一个索引超出范围的异常?

  public void addRemainingPrimes(int start, int end){

    for(int i = start; i < end; i+= 2){
      if(isPrime(i)){
        primes.add(i);
      }
    }
  }

  public boolean isPrime(int i) {
      int byteCell    = i / 16;
      int bit         = (i/2) % 8;
      return (numbers[byteCell] & (1 << bit)) == 0;

  }

在线程类中:

public void run(){
  //does stuff to find primes up to sqrt(n)

  updateRange();
  addRemainingPrimes(start, end);

}

public void updateRange(){
  if(id == 0){
    start = sqrt;
  }else{
    start = (((n - sqrt)/k) * id) + sqrt;
  }
  if(id == k-1){
    end = n;
  }else{
    end = start + ((n - sqrt) / k) - 1;
  }

}

number是大小为n的字节数组,primes是我的primeList的数组,n = 2.000.000,k是我使用的线程数,id是0到k-1。

我得到的错误:

Exception in thread "Thread-5" java.lang.ArrayIndexOutOfBoundsException: 6246
    at java.util.ArrayList.add(ArrayList.java:463)
    at ParallellSieve.addRemainingPrimes(ParallellSieve.java:162)
    at ParallellSieve$PrimeWorker.run(ParallellSieve.java:194)
    at java.lang.Thread.run(Thread.java:748)

0 个答案:

没有答案
相关问题