簡體   English   中英

在觀察者模式中使用線程

[英]Using threads with Observer Pattern

我有這個代碼:

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;
    }

}

基本上,我希望我的線程在每次調用 update() 方法時都做一些事情。 我不能在 update() 方法本身中做,因為它會在 Observable 調用 notifyObservers() 的同一線程中執行。 有什么方法可以向 run() 方法“發出信號”事件?

您可以通過阻塞並發隊列來實現消息傳遞。 然后classExample線程可以等待阻塞以等待通過隊列發送的新消息。 然后,當新消息到來時,該線程可以執行您最初想在 update 方法中執行的內容。

雖然其他人建議的阻塞隊列可以工作,但我不是它的忠實粉絲,因為它需要忙等待(消費者循環無限輪詢消息)。 另一種方法是每次Observer收到通知時提交任務。

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

輸出:

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() 然后做任何你想做的代碼

在非常基本的元素上:為什么不使用您在更新方法中設置的一些成員變量/標志?

eventWasFired = true;

在 run() 內部的 while 循環中,執行以下操作:

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

如果您有多個線程可以訪問您的 observable,您需要同步訪問並使用一些原子變量。 否則,您的程序將面臨數據競爭。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM