【问题标题】:How to fix NullPointerException in array of multithread app [duplicate]如何修复多线程应用程序数组中的 NullPointerException [重复]
【发布时间】:2018-05-11 09:03:17
【问题描述】:

我的任务:我需要在多个线程中生成矩阵的 BASE(数组)。线程可能根本不会生成矩阵,所以我尝试限制每个线程的生命周期。


我的想法:我制作了包含我的矩阵生成任务的 volatile 数组,并制作了包含线程和信息类的ConcurrentHashMap(任务数组中的索引和线程创建时间)


我的问题:当我尝试处理数组时,我得到了NullPointerException

线程信息类:

public class ThreadInformation {
    private long timeCreated;
    private int automatIndex;

    public ThreadInformation (long timeCreated, int automatIndex) {
        this.timeCreated = timeCreated;
        this.automatIndex = automatIndex;
    }

    public long getTimeCreated() {
        return timeCreated;
    }

    public int getIndex() {
        return automatIndex;
    }
}

多线程类:

public class MultiTaskGenerator {
    private final int BASE_SIZE = 10;
    private final Automat[] BASE = new Automat[BASE_SIZE];

    private static final int THREAD_COUNT = 8;
    private final int THREAD_LIVE_TIME_SEC = 10;

    private Map<Thread, ThreadInformation> threads = new ConcurrentHashMap<>();
    private volatile GeneratorTask[] tasks = new GeneratorTask[THREAD_COUNT];

    private int automatReady = 0;

    MultiTaskGenerator() {
        getThreadResult();
    }

    private void initThreads() {
        for (int i = 0; i < THREAD_COUNT; i++) {
            int j = i;
            System.out.println("Thread №" + j + " started");
            threads.put(new Thread(() -> {
                tasks[j] = new GeneratorTask();
            }), new ThreadInformation(System.currentTimeMillis(), j));
        }
        startThreads();
    }

    private void initNewThread(int index) {
        for (int i = 0; i < tasks.length; i++) {
            if (i == index) {
                threads.put(new Thread(() -> {
                    tasks[index] = new GeneratorTask();
                }), new ThreadInformation(System.currentTimeMillis(), index));
            }
        }
    }

    private void startThreads() {
        for (Thread thread : threads.keySet()) {
            Thread.State state = thread.getState();
            if (state == Thread.State.NEW) {
                thread.start();
            }
        }
    }

    private void getThreadResult() {
        initThreads();
        for (int i = 0; i < tasks.length; i++) {
            System.out.println(tasks[i]);
        }
        while (automatReady < BASE_SIZE) {
            Set mapSet = threads.entrySet();
            Iterator iterator = mapSet.iterator();
            while (iterator.hasNext()) {
                Map.Entry<Thread, ThreadInformation> mapEntry = (Map.Entry)iterator.next();

                if (!mapEntry.getKey().isAlive()) {
                    if (automatReady == BASE_SIZE) continue;
                    int currentIndex = mapEntry.getValue().getIndex();

                    BASE[automatReady] = tasks[currentIndex].getAutomat();
                    System.out.println("Добавлен автомат № " + automatReady);
                    automatReady++;
                    System.out.println("Thread №" + mapEntry.getValue().getIndex() + " finished successfully");
                    iterator.remove();
                    initNewThread(mapEntry.getValue().getIndex());
                    startThreads();
                    System.out.println("Thread №" + mapEntry.getValue().getIndex() + " started");
                } else {
                    if ((System.currentTimeMillis() - mapEntry.getValue().getTimeCreated()) < (THREAD_LIVE_TIME_SEC * 1000)) continue;
                    int taskIndex = mapEntry.getValue().getIndex();
                    tasks[taskIndex].stopGeneration(true);
                    System.out.println("Thread №" + taskIndex + " stoped");
                    mapEntry.getKey().interrupt();
                    iterator.remove();
                    System.out.println("Thread №" + taskIndex + " started");
                    initNewThread(mapEntry.getValue().getIndex());
                    startThreads();
                }
            }
        }
        threads.clear();
    }

    public Automat[] getBASE() {
        return BASE;
    }
}

堆栈跟踪:

Thread №0 started
Thread №1 started
Thread №2 started
Thread №3 started
Thread №4 started
Thread №5 started
Thread №6 started
Thread №7 started
null
null
null
null
null
null
null
null
Exception in thread "main" java.lang.NullPointerException
    at ru.stsz.MultiTaskGenerator.getThreadResult(MultiTaskGenerator.java:78)
    at ru.stsz.MultiTaskGenerator.<init>(MultiTaskGenerator.java:19)
    at ru.stsz.MainApp.main(MainApp.java:6)

谁能给我建议如何解决这个问题?

【问题讨论】:

  • 请发布堆栈跟踪错误以获得帮助。
  • 使用volatile 关键字只能保证原始字段、对象引用或不可变对象引用的字段的安全发布。数组不是上面列出的。
  • @Lorelorelore 我添加了堆栈跟踪。
  • 您在单独的线程中设置了tasks 的值,但您尝试在主线程中立即访问tasks。您的代码中没有等待线程完成的任何内容,因此无法确保 tasks 已正确初始化。
  • @MaxVollmer 那么我应该为什么更改数组?我现在不使用 getBase() 因为我无法填充基础。我只是在 main 中调用 new MultiTaskGenerator()

标签: java arrays multithreading nullpointerexception


【解决方案1】:

您可以在每次需要访问数组时添加断言!在 emty 数组的情况下是这样的:

public static void notEmpty(@Nullable Object[] array,String message) {
        if (ObjectUtils.isEmpty(array)) {
            throw new IllegalArgumentException(message);
        }
    }

【讨论】:

  • 你能解释一下为什么我在数组中得到空值吗?因为据我了解,它必须是到对象 threre 的链接,不是吗?如果我没有得到一个对象,我将无法通过我在这一行中的标志来停止它 - tasks[taskIndex].stopGeneration(true);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
  • 2023-04-04
  • 2014-06-23
  • 2020-06-24
  • 1970-01-01
  • 2018-08-18
相关资源
最近更新 更多