2017-07-06 5 views
-1

Ich habe diesen Code:Mit Gewinde mit 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; 
    } 

} 

Grundsätzlich möchte ich meinen Thread etwas jedes Mal, wenn die update() -Methode aufgerufen wird, zu tun. Ich kann nicht in der update() -Methode selbst tun, weil sie im selben Thread des Observable Calling notifyObservers() ausgeführt würde. Gibt es Möglichkeiten, ein Ereignis an die Methode run() zu "signalisieren"?

+1

ein Blocking verwenden. Senden Sie das Ereignis in der Warteschlange, wenn update() aufgerufen wird. Lies das Ereignis von der BlockingQueue in run(). –

Antwort

2

Sie können die Nachrichtenweiterleitung über das Blockieren gleichzeitiger Warteschlangen implementieren. Der Thread classExample könnte dann warten, um zu blockieren, dass neue Nachrichten über die Warteschlange gesendet werden. Dieser Thread könnte dann die Sachen ausführen, die Sie ursprünglich in der Update-Methode ausführen wollten, wenn eine neue Nachricht kommt.

-1

Bei den grundlegenden Elementen: Warum nicht einfach einige Membervariable/Flag verwenden, die Sie in Ihrer Update-Methode festgelegt haben?

eventWasFired = true; 

In Ihrem while-Schleife in der run() so etwas wie:

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

Sie brauchen Zugang zu synchronisieren und einige Atom-Variable verwenden, wenn Sie mehrere Threads haben, die Ihre beobachtbare zugreifen können. Andernfalls ist Ihr Programm Datenrennen ausgesetzt.

0

Während die blockierende Warteschlange, wie von anderen vorgeschlagen, funktionieren würde, bin ich kein großer Fan davon, weil es ein beschäftigtes Warten erfordert (der Verbraucher schleift unendlich nach einer Nachricht). Eine Alternative wäre, eine Aufgabe jedes Mal zu senden, wenn die Observer eine Benachrichtigung erhält.

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

Ausgang:

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. 
Verwandte Themen