简体   繁体   中英

Using threads with Observer Pattern

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?

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.

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.

如果你扩展线程类,你可以覆盖它的方法,然后你可以只使用 super() 然后做任何你想做的代码

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM