sergey_208
sergey_208

Reputation: 651

Out of Bound Exception when using parallel solving in Java

I am trying to solve multiple optimization instances in parallel and created a toy example. When I solve each instance with a single thread, it works fine. When I start increasing the number of threads, I receive out of memory exception for some instances. I was wondering if someone could give me a hint on how to fix this issue.

I tried my best to make the example as simple as possible.

import java.util.Iterator;
import java.util.Vector;

public class ConcurrentExample {
    public static int fixed;
    public static int nbWarehouses;
    public static int nbStores;
    public static void main(String[] args) throws IloException, InterruptedException {
        int nProblems = 20;

        final Vector<Integer> v = new Vector<Integer>();
        for (int i = 1; i <= nProblems; ++i) v.add(i);

        final Iterator<Integer> it = v.iterator();
        int nTHREADS = 2; //numofCores
        Thread[] threads = new Thread[nTHREADS ];

        for (int t = 0; t < nTHREADS ; ++t) {
              threads[t] = new Thread(new Runnable() {
                public void run() {
                while (true) {
                    int i;
                    synchronized (it) {
                      if ( !it.hasNext() ) return;
                      i = it.next();
                    }
                    fixed = 400 + i;
                    nbWarehouses = 400 ;
                    nbStores     = 800 + i;
                    int[] capacity = new int[nbWarehouses]; 
                    int[][]  supplyCost= new int[nbStores][nbWarehouses]; 
                    for(int w=0; w< nbWarehouses ; w++) {
                        capacity[w] = (nbStores/ nbWarehouses) + (w % ( nbStores/ nbWarehouses));
                        for(int s=0; s< nbStores ; s++) {
                            supplyCost[s][w] = 1 + ( ( s + 10 * w) % 100 );
                         }
                    }
                }
               }
            }
          );
        }

        for (int t = 0; t < nTHREADS; ++t) { threads[t].start(); }

        for (int t = 0; t < nTHREADS; ++t) { threads[t].join(); }


    }

}

When I use two threads, I receive the following error:

Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: 801
    at concurrent$1.run(concurrent.java:36)
    at java.lang.Thread.run(Thread.java:748)

When I set NTHREADS=4, then I receive the following error.

Exception in thread "Thread-1" Exception in thread "Thread-0" Exception in thread "Thread-2" java.lang.ArrayIndexOutOfBoundsException: 802
    at concurrent$1.run(concurrent.java:36)
    at java.lang.Thread.run(Thread.java:748)
java.lang.ArrayIndexOutOfBoundsException: 801
    at concurrent$1.run(concurrent.java:36)
    at java.lang.Thread.run(Thread.java:748)
java.lang.ArrayIndexOutOfBoundsException: 803
    at concurrent$1.run(concurrent.java:36)
    at java.lang.Thread.run(Thread.java:748)

EDIT: One very important thing is that I have to keep the variables as globally defined. This is just a toy example. In the real model, I have static variables which are accessed by multiple methods during an iterative solution approach.

Upvotes: 0

Views: 147

Answers (2)

DQYuan
DQYuan

Reputation: 177

Why use so many static field? There will be no problem if you use local variables:

import java.util.Iterator;
import java.util.Vector;

public class ConcurrentExample {

    public static void main(String[] args) throws InterruptedException {
        int nProblems = 20;

        final Vector<Integer> v = new Vector<Integer>();
        for (int i = 1; i <= nProblems; ++i) v.add(i);

        final Iterator<Integer> it = v.iterator();
        int nTHREADS = 2; //numofCores
        Thread[] threads = new Thread[nTHREADS];

        for (int t = 0; t < nTHREADS ; ++t) {
            threads[t] = new Thread(new Runnable() {
                public void run() {
                    while (true) {
                        int i;
                        synchronized (it) {
                            if ( !it.hasNext() ) return;
                            i = it.next();
                        }

                        int nbWarehouses = 400 ;
                        int nbStores     = 800 + i;
                        int[] capacity = new int[nbWarehouses];
                        int[][]  supplyCost= new int[nbStores][nbWarehouses];
                        for(int w=0; w< nbWarehouses ; w++) {
                            capacity[w] = (nbStores/ nbWarehouses) + (w % ( nbStores/ nbWarehouses));
                            for(int s=0; s< nbStores ; s++) {
                                supplyCost[s][w] = 1 + ( ( s + 10 * w) % 100 );
                            }
                        }
                    }
                }
            }
            );
        }

        for (int t = 0; t < nTHREADS; ++t) { threads[t].start(); }

        for (int t = 0; t < nTHREADS; ++t) { threads[t].join(); }


    }

}

Upvotes: 0

Muthu
Muthu

Reputation: 51

When two threads started, "nbStores" may be incremented, through which iteration done on line 36 may get ArrayIndexOutOfException.

First thread starts with int[][] supplyCost= new int[nbStores][nbWarehouses];//nbStores=801 Once second thread started, nbStores will become 802, which may affect the loop to run till s=801. for(int s=0; s< nbStores ; s++)

Upvotes: 0

Related Questions