Skip to main content

多執行緒

簡介

Playwright Java 並不是執行緒安全的,也就是說,所有其方法以及所有由其建立的物件(例如 BrowserContextBrowserPage 等)都應該在建立 Playwright 物件的同一執行緒上呼叫,或者應實作適當的同步化以確保在任何給定時間只有一個執行緒呼叫 Playwright 方法。話雖如此,可以在各自的執行緒上建立多個 Playwright 實例。

這裡是一個範例,其中三個 Playwright 實例分別在各自的執行緒上建立。每個實例啟動自己的瀏覽器程序並對其進行測試。

package org.example;

import com.microsoft.playwright.*;

import java.nio.file.Paths;

import static java.util.Arrays.asList;

public class PlaywrightThread extends Thread {
private final String browserName;

private PlaywrightThread(String browserName) {
this.browserName = browserName;
}

public static void main(String[] args) throws InterruptedException {
// Create separate playwright thread for each browser.
for (String browserName: asList("chromium", "webkit", "firefox")) {
Thread thread = new PlaywrightThread(browserName);
thread.start();
}
}

@Override
public void run() {
try (Playwright playwright = Playwright.create()) {
BrowserType browserType = getBrowserType(playwright, browserName);
Browser browser = browserType.launch();
Page page = browser.newPage();
page.navigate("https://playwright.dev/");
page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("user-agent-" + browserName + ".png")));
}
}

private static BrowserType getBrowserType(Playwright playwright, String browserName) {
switch (browserName) {
case "chromium":
return playwright.chromium();
case "webkit":
return playwright.webkit();
case "firefox":
return playwright.firefox();
default:
throw new IllegalArgumentException();
}
}
}

同步 API 和事件分派

在同步的 Playwright API 中,所有事件僅在 Playwright 執行其訊息迴圈時才會被分派。當你呼叫任何 API 方法時,這會自動發生,如果堆疊上沒有活躍的 Playwright 呼叫,則不會發生。如果你需要等待一個事件,最好的方法是通過 waitFor* 方法之一來完成。

Page.waitForTimeout() vs. Thread.sleep()

同步 API 的一個後果是,如果你因為某種原因呼叫 Thread.sleep(),那麼當執行緒在睡眠時不會觸發任何事件。如果你希望在程式執行時從瀏覽器分派事件

執行已暫停使用 Page.waitForTimeout()Frame.waitForTimeout():

page.onResponse(response -> System.out.println(response.url()));
page.navigate("https://playwright.dev");
System.out.println("-- did navigate --");
// Block current thread for 60s and ensure the events are dispatched.
page.waitForTimeout(60_000);