-1

I have a exercise from ThinkingInJava book: "//Exercise 22: (4) Create an example of a busy wait.One task sleeps for a while and then sets a flag to true.The second task watches that flag inside a while loop(this is the busy wait) and when the flag becomes true,sets it back to false and reports the change to the console.Note how much wasted time the program spends inside the busy wait,and create a second version of the program that uses wait( ) instead of the busy wait" But when I run a programm I always get a NullPointerException and I don't the reason of It. Im initialized all fields and run a programm in a proper sequence. The exception is here and connected with flag field.:

"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();
    }
}

1 Answers1

0

You are not initializing Locker.switcher instead, you are just re-writing the parameter. Instead you need to use 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();
        // ...
    }
}

Since you are just re-writing the parameter your switcher field stays null amd thus gets you a NPE when you try to reference it.

xtratic
  • 4,600
  • 2
  • 14
  • 32