提问人:Nikolay Nickolskiy 提问时间:2/18/2021 更新时间:2/18/2021 访问量:98
多线程程序中的 nullpointerexception 问题 [duplicate]
A problem with nullpointerexception in multithread programm [duplicate]
问:
我在 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();
}
}
答:
0赞
xtratic
2/18/2021
#1
您不是在初始化,而只是在重写参数。相反,您需要使用Locker.switcher
this.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。switcher
null
评论