多线程程序中的 nullpointerexception 问题 [duplicate]

A problem with nullpointerexception in multithread programm [duplicate]

提问人:Nikolay Nickolskiy 提问时间:2/18/2021 更新时间:2/18/2021 访问量:98

问:

我在 ThinkingInJava 书中有一个练习: “//练习 22:(4) 创建一个繁忙等待的例子。一个任务休眠了一段时间,然后将标志设置为 true。第二个任务在 while 循环中监视该标志(这是繁忙的等待),当该标志变为 true 时,将其设置回 false 并将更改报告给控制台。注意程序在繁忙的等待中浪费了多少时间,并创建使用 wait( ) 而不是繁忙等待的程序的第二个版本“ 但是当我运行一个程序时,我总是得到一个 NullPointerException,我不知道它的原因。 我初始化了所有字段并按正确的顺序运行程序。例外在这里,并与标志字段连接。

"Exception in thread "pool-1-thread-2" java.lang.NullPointerException
    at ThinkingInJava.Concurrency.P882.Locker.checkFlag(BusyWait.java:46)
    at ThinkingInJava.Concurrency.P882.Locker.run(BusyWait.java:55)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)


class Switcher implements Runnable {
private volatile boolean flag = false;
@Override
public void run() {
    try {
        TimeUnit.MILLISECONDS.sleep(100);
    } catch (InterruptedException e) {
        System.out.println(e);
    }
    flag = true;
}
public synchronized boolean getFlag() { return flag; }
public void setFlagToFalse() {
    flag = false;
    System.out.println(flag);
}

@Override
public String toString() {
    return "Swither turn " + flag;
}

}

class Locker implements Runnable {
    private Switcher switcher;
    private volatile boolean flag;
    public Locker(Switcher switcher) {
        switcher = switcher;
        flag = switcher.getFlag();
        System.out.println("Class Switcher: " + switcher);
        System.out.println("field flag: " + flag);
    }
    public void checkFlag() {
        if(switcher.getFlag())
            flag = switcher.getFlag();
    }
    public boolean getFlag() { return switcher.getFlag(); }
    @Override
    public void run() {
       // System.out.println(switcher);
        long start = System.currentTimeMillis();
        while (true) {
            checkFlag();
            if(flag) {
               flag = false;
               long duration = System.currentTimeMillis() - start;
               System.out.println(duration);
               return;
            }
        }
    }
}

public class BusyWait {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        Switcher switcher = new Switcher();
        Locker locker = new Locker(switcher);
        exec.execute(switcher);
        exec.execute(locker);
        exec.shutdown();
    }
}
Java 多线程 NullPointerException

评论


答:

0赞 xtratic 2/18/2021 #1

您不是在初始化,而只是在重写参数。相反,您需要使用Locker.switcherthis.switcher = switcher;

class Locker implements Runnable {
    private Switcher switcher;
    private volatile boolean flag;

    public Locker(Switcher switcher) {
        // The below just re-writes the parameter and NOT the `this.switcher` field
        switcher = switcher;

        flag = switcher.getFlag();
        // ...
    }
}

由于您只是在重写参数,因此您的字段保持 amd 状态,因此当您尝试引用它时,它会为您提供 NPE。switchernull