多執行緒
簡介
Playwright Java 不是執行緒安全的,也就是說,它的所有方法以及它建立的所有物件(例如 BrowserContext、Browser、Page 等)的方法都應該在建立 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.org.tw/");
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() 與 Thread.sleep()
同步 API 的一個後果是,如果您因為任何原因呼叫 Thread.sleep(),則在執行緒休眠時不會觸發任何事件。如果您希望在程式
執行暫停時,要讓瀏覽器的事件分發,請使用 Page.waitForTimeout() 或 Frame.waitForTimeout()
page.onResponse(response -> System.out.println(response.url()));
page.navigate("https://playwright.dev.org.tw");
System.out.println("-- did navigate --");
// Block current thread for 60s and ensure the events are dispatched.
page.waitForTimeout(60_000);