JCD
JCD

Reputation: 13

Why is the ArrayList not updated in the following example?

I am using the JNativeHook library.

An instance of GlobalKeyListener starts listening to Keystrokes and adds them to arrayList1; problem is that the arrayList1 does not seem to get updated (list1itemCount does never get bigger then 0) when accessing it over the infinite while(true) loop in the Child class. Why is that and what must I do to achieve that?

public class Child {
    public static void main(String[] args) {
        // Get the logger for "org.jnativehook" and set the level to warning.
        Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
        logger.setLevel(Level.WARNING);
        try {
            GlobalScreen.registerNativeHook();
        }
        catch (NativeHookException ex) {
            System.err.println("There was a problem registering the native hook.");
            System.err.println(ex.getMessage());

            System.exit(1);
        }

        GlobalKeyListener globalkeylistener = new GlobalKeyListener();
        GlobalScreen.addNativeKeyListener(globalkeylistener);
        Connection conn;
        while(true){
            int list1itemCount = globalkeylistener.arrayList1.size();
            if (list1itemCount >= 4)
                System.out.println(list1itemCount);
        }
    }
}

GlobalKeyListener Class:

public class GlobalKeyListener implements NativeKeyListener {
    ArrayList<Class1> arrayList1 = new ArrayList<>();
    public ArrayList<Class1> listing() {
        return arrayList1;
    }

    public void nativeKeyPressed(NativeKeyEvent e) {
        arrayList1.add(new Class1(e.getKeyCode(), 1));
    }

    public void nativeKeyReleased(NativeKeyEvent e) {
        arrayList1.add(new Class1(e.getKeyCode(), 0));
    }

    public void nativeKeyTyped(NativeKeyEvent e) {
    }
}

Upvotes: 0

Views: 92

Answers (1)

durron597
durron597

Reputation: 32323

This is a multithreading issue. The keyEvent updates occur on a different thread, and your while(true) won't update. Also, the ArrayList itself is not threadsafe as you've written it.

It would be better to synchronize on something (the easiest, not necessarily best) thing is the key listener itself, and have it wait until the update occurs and then notify. Here's the modified code:

GlobalKeyListener.java

public class GlobalKeyListener implements NativeKeyListener {
  ArrayList<Class1> arrayList1 = new ArrayList<>();
  public ArrayList<Class1> listing() {
      return arrayList1;
  }

  public void nativeKeyPressed(NativeKeyEvent e) {
    synchronized(this) {
      arrayList1.add(new Class1(e.getKeyCode(), 1));
      this.notifyAll();
    }
  }

  public void nativeKeyReleased(NativeKeyEvent e) {
    synchronized(this) {
      arrayList1.add(new Class1(e.getKeyCode(), 0));
      this.notifyAll();
    }
  }

  public void nativeKeyTyped(NativeKeyEvent e) {
  }
}

Child.java

public class Child {
  public static void main(String[] args) throws InterruptedException {
    Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
    logger.setLevel(Level.WARNING);
      try {
          GlobalScreen.registerNativeHook();
      }
      catch (NativeHookException ex) {
          System.err.println("There was a problem registering the native hook.");
          System.err.println(ex.getMessage());

          System.exit(1);
      }

      GlobalKeyListener globalkeylistener = new GlobalKeyListener();
      GlobalScreen.addNativeKeyListener(globalkeylistener);
      synchronized(globalkeylistener) {
        while(true){
            int list1itemCount = globalkeylistener.arrayList1.size();
            if (list1itemCount >= 4) {
                System.out.println(list1itemCount);
            }
            globalkeylistener.wait();
        }
      }
  }
}

Upvotes: 1

Related Questions