Aktivt objekt - Active object

Det aktiva objektdesignmönstret kopplar bort metodutförande från metodinvokation för objekt som var och en har sin egen tråd av kontroll. Målet är att introducera samtidighet genom att använda asynkron metodinvokation och en schemaläggare för hantering av förfrågningar.

Mönstret består av sex element:

  • En proxy , som ger ett gränssnitt mot kunder med allmänt tillgängliga metoder.
  • Ett gränssnitt som definierar metodbegäran för ett aktivt objekt.
  • En lista över väntande förfrågningar från klienter.
  • En schemaläggare som bestämmer vilken begäran som ska köras nästa.
  • Implementeringen av metoden för aktivt objekt.
  • En återuppringning eller variabel för att klienten ska få resultatet.

Exempel

Java

Ett exempel på aktivt objektmönster i Java .

För det första kan vi se en standardklass som tillhandahåller två metoder som ställer in en dubbel till ett visst värde. Denna klass överensstämmer INTE med det aktiva objektmönstret.

class MyClass {

    private double val = 0.0;
    
    void doSomething() {
        val = 1.0;
    }

    void doSomethingElse() {
        val = 2.0;
    }
}

Klassen är farlig i ett flertrådsscenario eftersom båda metoderna kan kallas samtidigt, så värdet av val (som inte är atomärt - det uppdateras i flera steg) kan vara odefinierat - ett klassiskt rasvillkor. Du kan naturligtvis använda synkronisering för att lösa detta problem, vilket i detta triviala fall är enkelt. Men när klassen blivit realistiskt komplex kan synkronisering bli mycket svår.

Om du vill skriva om den här klassen som ett aktivt objekt kan du göra följande:

class MyActiveObject {

    private double val = 0.0;
    private BlockingQueue<Runnable> dispatchQueue = new LinkedBlockingQueue<Runnable>();

    public MyActiveObject() {
        new Thread (new Runnable() {
                    
                @Override
                public void run() {
                    try {
                        while (true) {
                            dispatchQueue.take().run();
                        }
                    } catch (InterruptedException e) {   
                        // okay, just terminate the dispatcher
                    }
                }
            }
        ).start();
    }

    void doSomething() throws InterruptedException {
        dispatchQueue.put(new Runnable() {
                @Override
                public void run() { 
                    val = 1.0; 
                }
            }
        );
    }

    void doSomethingElse() throws InterruptedException {
        dispatchQueue.put(new Runnable() {
                @Override
                public void run() { 
                    val = 2.0; 
                }
            }
        );
    }
}

Java 8 (alternativ)

Ett annat exempel på aktivt objektmönster i Java istället implementerat i Java 8 ger en kortare lösning.

public class MyClass {
    private double val; 
    
    // container for tasks
    // decides which request to execute next 
    // asyncMode=true means our worker thread processes its local task queue in the FIFO order 
    // only single thread may modify internal state
    private final ForkJoinPool fj = new ForkJoinPool(1, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);
    
    // implementation of active object method
    public void doSomething() throws InterruptedException {
        fj.execute(() -> { val = 1.0; });
    }
 
    // implementation of active object method
    public void doSomethingElse() throws InterruptedException {
        fj.execute(() -> { val = 2.0; });
    }
}

Se även

Referenser

externa länkar