2016-04-07 7 views

Antwort

1

Stellen Sie sich ein Restaurant vor. Denk an einen Tisch. Eine Tabelle hat keine Möglichkeit, den gleichzeitigen Zugriff zu steuern (wie eine Ampel), so dass sie nicht als Thread-sicher gilt. Wenn es einen einzigen Tisch gäbe, würden alle Gäste um einen Platz kämpfen, wo sie sitzen oder auf einem Stuhl sitzen könnten. Eine Lösung wäre, dass jeder Gast seine eigene Tabelle (Instanzvariable) mitbringt, aber das würde den Platz des Restaurants füllen. Stattdessen haben Sie einen Tisch für jede Gruppe von Gästen. Und solange Sie auf dem Tisch sitzen, haben Sie exklusiven Zugriff darauf. Sobald die Gruppe der Gäste gegangen ist, kann die nächste Gruppe von Gästen darauf zugreifen, so dass es eine gemeinsame Ressource ohne gleichzeitigen Zugriff ist. Die Tabelle im Beispiel ist ein ThreadLocal.

Es gibt zwei Möglichkeiten, den Thread lokal zu initialisieren - mit oder ohne Anfangswert.

Ohne Anfangswert

wenn Sie Worker-Threads haben, die wiederverwendet werden. Sie legen das ThreadLocal fest, wenn die Taskausführung beginnt, und löschen es gegebenenfalls.

static ThreadLocal<YourType> LOCAL = new ThreadLocal<>(); 

void beginWork() { 
    LOCAL.set(yourTypeInstance); 
} 

Mit Anfangswert

, wenn Sie sicherstellen wollen, dass der Wert initialisiert und der Wert selbst ist nicht kontextuellen, ähnlich einem Singleton und unterscheidet sich von der Aufgabe Beispiel.

static ThreadLocal<YourType> LOCAL = ThreadLocal.withInitialValue(() -> new YourType()); 

void beginWork() { 
    YourType localInstance = LOCAL.get(); 
} 

Wichtig! ThreadLocal ist ein Konzept für gemeinsame Werte und sollte immer statische Referenzen sein, die Verwendung von nicht-statischen Referenzen könnte ziemlich schlechte Speicherverluste (Instanz pro Objekt und per-Thread) führen.

Während Singletons freigegebene Ressourcen mit gleichzeitiger Zugriffsoption sind, sind Thread Locals freigegebene Ressourcen mit sequenziellem Zugriff. Objekte im lokalen Thread müssen nicht Thread-sicher sein. Technisch werden die threadlokalen Objekte in einem speziellen Bereich des Speichers gehalten, zu dem nur der Thread exklusiven Zugriff hat.

Für Ihre konkrete Frage, ein Thread lokaler Sinn für Ihre Fabrik machen würde, wenn

  • Ihr Werk nicht sicher ist, fädelt
  • Ihre Fabrik hat einen Zustand, der nicht unter den Threads gemeinsam genutzt werden soll

Wenn Sie Thread lokal dafür verwenden, verwenden Sie die Option mit Initialwert, um die Fabrik einmal pro verwendetem Thread zu erstellen

Angesichts der Informationen yo Wenn ich Ihnen zur Verfügung stehe, würde ich vorschlagen, stattdessen die Threadsicherheitsprobleme zu beheben. Das POM sollte durch Tests leicht wiederverwendbar sein und keinen gemeinsamen Status haben (statischer Zugriff). Das Gleiche gilt für die Fabrik. Und Sie sollten auch einen separaten WebDriver pro Thread verwenden, aber es sollte völlig in Ordnung sein, einen Test pro Instanz als Instanzvariable zu erstellen, ohne einen lokalen Thread zu verwenden und ihn dem POM zuzuordnen.

Aber keine Regel ohne Ausnahme, auf die Umsetzung je nach Modell, können Sie es um einen aktuellen Kontext entwickelt haben, die einen Verweis auf den aktuellen Treiber hält, so könnte man eine statische Getter-Methode für den Fahrer haben. In diesem Fall ist ThreadLocal der richtige Weg.

class TestContext { 

    static ThreadLocal<WebDriver> CURRENT_DRIVER = ThreadLocal.withInitialValue(() -> new FirefoxDriver()); 

    static WebDriver currentDriver(){ 
    return CURRENT_DRIVER.get(); 
    } 
} 

//your POM 
class LoginPage { 
    void login(String username) { 
    TestContext.currentDriver().getElementById(...).sendKeys(username); 
    //... 
    } 
} 
+0

hi @ Gerald danke für Sie wertvolle Erklärung. Jedes Mal, wenn man eine einzelne Methode aufruft, ist das keine gute Idee. Ich muss lokale Thread-Struktur implementieren, indem ich meinen WebDriver in der Basisklasse initialisiere und der in POM wiederverwendbar sein kann. Kann ich stattdessen "@BeforeMethod" TestNG Annotation verwenden? –

+0

sicher, es ist die Option ohne Anfangswert (siehe oben) –

+0

Lets macht Dinge einfach, wenn ich meinen Treiber statisch initialisieren ThreadLocal driver = new ThreadLocal (); @BeforeAnnotation public WebDriver getDriver() {driver.get(); } Wie wird es in meinen Unterklassen funktionieren? –

Verwandte Themen