Wielowątkowo po tablicy znaleźć min,max,suma

0

To mój pierwszy powiedzmy "średniej" wielkości program wielowątkowy, tabela ma być podzielona na części dla każdego z wątków, wszystko w jednej klasie. Ostatni wątek liczy wszystkie miny,maxy,sumy z reszty wątków. Wyrzuca null pointer exception

import java.util.*;

public class ThreadArrayProgram  {

    static Random random = new Random();
    static Scanner scanner = new Scanner(System.in);
    static int[] array;
    static Thread[] threadArray;
    static int arrayLength;
    static int numOfThreads;
    static HashMap<Integer, Integer> threadStarts = new HashMap<>();
    static HashMap<Integer, Integer> threadEnds = new HashMap<>();
    static int indexA;
    static List<Integer> minList = new ArrayList<>();
    static List<Integer> maxList = new ArrayList<>();
    static List<Integer> listaSum = new ArrayList<>();
    static int maxOfArray;
    static int minOfArray;
    static Integer sumOfArray;





    static void fillArray() {
        for (int i = 0; i < arrayLength; i++) {
            array[i] = random.nextInt(10000);
            System.out.print(array[i] + " ");
        }

    }


    public static void main(String[] args) throws InterruptedException {
        System.out.println(" Give length of array  ");
        arrayLength = scanner.nextInt();

        System.out.println(" Give the amount of threads ");
        numOfThreads = scanner.nextInt();

        array = new int[arrayLength];
        threadArray = new Thread[numOfThreads];

        fillArray();
        divideArray();
        initializeThreads();
        for (int i = 0; i < threadArray.length-1; i++) {
            threadArray[i].start();
        }
        for (int i = 0; i < threadArray.length-1; i++) {
            threadArray[i].join();
        }
        threadArray[threadArray.length-1].start();
        threadArray[threadArray.length-1].join();

        System.out.println();
        System.out.println("Max  z tabeli = " + maxOfArray);
        System.out.println("Min  z tabeli = " + minOfArray);
        System.out.println("Suma  z tabeli = " + sumOfArray);
    }

    static void divideArray() {
        int arrayPart;
        int lastThread;
        if(numOfThreads == 1){
             arrayPart = arrayLength;
             lastThread = 0;
        }else   {
             arrayPart = (int) Math.ceil(arrayLength / (numOfThreads - 1));
            lastThread = arrayLength % (numOfThreads - 1);
        }

        int index = 1;
        int i;
        for (i = 0; i < arrayLength - lastThread; i++) {

            threadStarts.put(index, i);
            i += (arrayPart - 1);
            threadEnds.put(index, i);
            index++;
        }
        if (lastThread != 0) {
            threadStarts.put(index, i);
            threadEnds.put(index, i + lastThread - 1);
        }
    }


    static void initializeThreads() {
        if (numOfThreads == 1) {
           threadArray[0] = new Thread(new Runnable() {

                int sum = 0;
                 int max = 0;
                int min = array[0];

                @Override
                public void run() {
                    for (int i = 0; i < array.length; i++) {


                        sum += array[i];
                        if (array[i] > max) {
                            max = array[i];
                        } else if (array[i] < min) {
                            min = array[i];

                        }

                    }
                    maxOfArray = max;
                    minOfArray = min;
                    sumOfArray = Integer.valueOf(sum);
                }
            });
        } else {
            indexA = 1;
            for (int i = 0; i < numOfThreads - 1; i++) {


                threadArray[i] = new Thread(new Runnable() {

                    @Override
                    public void run() {


                        int min = array[threadStarts.get(Integer.valueOf(indexA))];
                        int max = 0;
                        int sum = 0;

                        for (int j = threadStarts.get(Integer.valueOf(indexA)); j <= threadEnds.get(Integer.valueOf(indexA)); j++) {
                            sum += array[j];
                            if (array[j] > max) {
                                max = array[j];
                            } else if (array[j] < min) {
                                min = array[j];

                            }

                        }
                        synchronized (this) {
                            maxList.add(max);
                            minList.add(min);
                            listaSum.add(sum);
                        }
                    }
                });
                indexA++;
            }
            threadArray[numOfThreads -1] = new Thread(new Runnable() {

                @Override
                public void run() {
                     minOfArray = Collections.min(minList);
                     maxOfArray = Collections.max(maxList);
                     sumOfArray = listaSum.stream()
                            .mapToInt(Integer::intValue)
                            .sum();
                }
            });

        }
    }


}

**Po wprowadzeniu danych wyrzuca : **
Exception in thread "Thread-1" Exception in thread "Thread-0" java.lang.NullPointerException
at ThreadArrayProgram$2.run(ThreadArrayProgram.java:127)
at java.base/java.lang.Thread.run(Thread.java:844)
java.lang.NullPointerException
at ThreadArrayProgram$2.run(ThreadArrayProgram.java:127)
at java.base/java.lang.Thread.run(Thread.java:844)
Exception in thread "Thread-2" java.util.NoSuchElementException
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:894)
at java.base/java.util.Collections.min(Collections.java:598)
at ThreadArrayProgram$3.run(ThreadArrayProgram.java:154)
at java.base/java.lang.Thread.run(Thread.java:844)

Choć widoczne są linijki błędu czyli :

int min = array[threadStarts.get(Integer.valueOf(indexA))];

oraz minOfArray = Collections.min(minList);
nie mam pojęcia co powinienem zrobić. Bardzo proszę o pomoc!

1

Nie jestem pewien jak konkretnie w Javie działają domknięcia, lecz czy przypadkiem indexA nie zostaje złapane przez referencję (zamiast wartość, tak jak zakładasz)?

Wówczas podczas threadStarts.get(Integer.valueOf(indexA)) odwoływałbyś się nie do indeksu złapanego w trakcie iteracji, tylko do ostatniego (a dokładniej to ostatniego + 1 z powodu indexA++), przez co threadStarts.get() zwróciłoby nulla bądź działyby się inne cuda.

1 użytkowników online, w tym zalogowanych: 0, gości: 1