マルチスレッド
はじめに
Playwright Javaはスレッドセーフではありません。つまり、そのすべてのメソッドと、それによって作成されたすべてのオブジェクト(BrowserContext、Browser、Pageなど)のメソッドは、Playwrightオブジェクトが作成されたスレッドと同じスレッドで呼び出されるか、または、任意の時点でPlaywrightメソッドを呼び出すスレッドが1つだけになるように適切な同期を実装する必要があります。とはいえ、複数のPlaywrightインスタンスをそれぞれ独立したスレッドで作成することは問題ありません。
以下は、3つの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.dokyumento.jp/");
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の1つの結果として、何らかの理由で`Thread.sleep()`を呼び出すと、スレッドがスリープしている間はイベントが発火しません。プログラム
実行が一時停止している間にブラウザからのイベントをディスパッチしたい場合は、Page.waitForTimeout()またはFrame.waitForTimeout()を使用してください。
page.onResponse(response -> System.out.println(response.url()));
page.navigate("https://playwright.dokyumento.jp");
System.out.println("-- did navigate --");
// Block current thread for 60s and ensure the events are dispatched.
page.waitForTimeout(60_000);