2016-03-30 9 views
0

Wenn eine Seiten- oder Komponentenklasse ein Instanzfeld hat, das ein nicht synchronisiertes Objekt ist, z. ein ArrayList, und die Anwendung hat Code, der dieses Feld strukturell ändert, sollte der Zugriff auf dieses Feld synchronisiert werden?Sollen Instanzfelder auf einer Tapestry-Seite oder -Komponente synchronisiert werden?

f.ex .:

public class MyPageOrComponent 
{ 
    @Persist 
    private List<String> myList; 

    void setupRender() 
    { 
     if (this.myList == null) 
     { 
      this.myList = new ArrayList<>(); 
     } 
    } 

    void afterRender(MarkupWriter writer) 
    { 
     // Should this be synchronized ? 

     if (someCondition) 
     { 
      this.myList.add(something); 
     } 
     else 
     { 
      this.myList.remove(something); 
     } 
    } 
} 

Ich frage, weil ich zu verstehen scheinen, dass Tapestry nur eine Instanz einer Seite oder eines Komponentenklasse erstellt und verwendet diese Instanz für alle angeschlossenen Clients (aber bitte korrigiere mich, wenn das nicht stimmt).

Antwort

1

Kurz gesagt ist die Antwort nein, Sie müssen nicht, weil Tapestry dies für Sie tut. Tapestry transformiert Ihre Seiten und Klassen für Sie zur Laufzeit so, dass sie, wo auch immer Sie mit Ihren Feldern interagieren, nicht tatsächlich an der Instanzvariablen, sondern an einer verwalteten Variablen arbeiten, die Thread-sicher ist. Die vollständigen inneren Abläufe sind jenseits von mir, aber eine kurze Referenz auf die Transformation finden Sie here.

Eine Warnung: Instanziieren Sie Ihre Seiten-/Komponentenvariablen nicht bei der Deklaration. Ich habe ein seltsames Verhalten dabei gesehen. Tun Sie das nicht:

private List<String> myList = new ArrayList<String>; 
1

Tapestry verwendet einige Laufzeit-Byte-Code-Magie, um Ihre Seiten und Komponenten zu transformieren. Seiten und Komponenten sind Singletons, aber die Eigenschaften werden so transformiert, dass sie von einem PerThreadValue unterstützt werden. Dies bedeutet, dass jede Anfrage ihre eigene Kopie des Wertes erhält, so dass keine Synchronisation erforderlich ist.

Wie von @joostschouten vorgeschlagen, sollten Sie eine veränderbare Eigenschaft niemals in der Felddeklaration initialisieren. Das seltsame Verhalten, das er diskutiert, wird verursacht, weil dies von allen Anfragen geteilt wird (da der Initialisierer nur einmal für die Seite/Komponente Singleton ausgelöst wird). Veränderbare Felder sollten stattdessen in einer Rendermethode (z. B. @SetupRender)

initialisiert werden