0

I have this code:

public class classExample implements Observer Runnable {

    public classExample() {
    //...
    }

    @Override
    public void run() {
        while (true) {
           //wait for EVENT;
           //do something;
        }
    }

    @Override
    public void update(Observable arg0, Object arg1) {
    //signal EVENT;
    }

}

Basically, i want my thread to do something every time the update() method is called. I can't do in the update() method itself cause it would be executed in the same thread of the Observable calling notifyObservers(). Are there any ways to "signal" an event to the run() method?

Maffe
  • 430
  • 6
  • 14
  • 1
    Use a BlockingQueue. Send the event in the queue when update() is called. Read the event from the BlockingQueue in run(). – JB Nizet Jul 06 '17 at 21:30

4 Answers4

2

You could implement message passing via blocking concurrent queues. The classExample thread could then wait blocking for new messages to be sent via the queue. This thread could then execute the stuff you originally wanted to execute in the update method, when a new message comes.

Sebastian Walla
  • 1,104
  • 1
  • 9
  • 23
0

While the blocking queue as suggested by others would work, I'm not a big fan of it because it requires a busy wait (the consumer loops infinitely polling for a message). An alternative would be to submit a task every time the Observer receives a notification.

public class Main extends Observable implements Observer {
    private final int numCores = Runtime.getRuntime().availableProcessors();
    private final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numCores);

    public Main() {
        addObserver(this);
    }

    public static void main(String[] args) throws InterruptedException {
        new Main().execute();
    }

    private void execute() {
        for (int i = 0; i < 5; ++i) {
            this.setChanged();
            this.notifyObservers(i);

            try {
                Thread.sleep(1000l);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        executor.shutdown();
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.printf("Received notification on thread: %s.\n", Thread.currentThread().getName());
        executor.submit(() -> System.out.printf("Running in thread: %s, result: %s.\n",
                Thread.currentThread().getName(), arg));
    }
}

Output:

Received notification on thread: main.
Running in thread: pool-1-thread-1, result: 0.
Received notification on thread: main.
Running in thread: pool-1-thread-2, result: 1.
Received notification on thread: main.
Running in thread: pool-1-thread-3, result: 2.
Received notification on thread: main.
Running in thread: pool-1-thread-4, result: 3.
Received notification on thread: main.
Running in thread: pool-1-thread-5, result: 4.
Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219
0

If you extend the thread class, you can override its methods and then you can just use super() and then do whatever code you want

-1

At the very basic elements: Why not just use some membervariable/flag that you set in your update-Method?

eventWasFired = true;

In your while-loop inside of run() do something like:

try {
    Thread.sleep(updateTimer);
    if(eventWasFired) {
         doSomeAction();
         eventWasFired = false;
    }
} catch (InterruptedException ie) {
    // handle if you like
}

you need to synchronize access and use some atomic-variable if you have multiple threads that may access your observable. Otherwise your program is exposed to data races.

Sebastian Walla
  • 1,104
  • 1
  • 9
  • 23