2017-07-06 163 views
-1

使用線程我有這樣的代碼:與觀察者模式

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()方法本身中執行,因爲它會在調用notifyObservers()的Observable的同一個線程中執行。 有什麼方法可以將事件「發信號」給run()方法嗎?

+1

使用的BlockingQueue。當update()被調用時發送隊列中的事件。從run()中的BlockingQueue中讀取事件。 –

回答

2

您可以通過阻止併發隊列來實現消息傳遞。 classExample線程可能會等待阻止新消息通過隊列發送。這個線程可以執行最初想要在update方法中執行的內容,當有新消息出現時。

-1

在最基本的元素:爲什麼不只是使用您在更新中設置的一些membervariable/flag-Method?

eventWasFired = true; 

在運行裏面的while循環()做這樣的事情:

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

需要同步接入和使用一些原子變量,如果您有可以訪問您觀察到的多個線程。否則你的程序會暴露於數據競賽。

0

雖然其他人建議的阻塞隊列可以工作,但我並不是很喜歡它,因爲它需要忙於等待(消費者循環無限輪詢消息)。另一種選擇是在每次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.