メインコンテンツにスキップ

マルチスレッド

概要

Playwright Java はスレッドセーフではありません。つまり、Playwright オブジェクトによって作成されたすべてのオブジェクト (例えば 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);