跳至主要内容

多线程

简介

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.net.cn/");
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.net.cn");
System.out.println("-- did navigate --");
// Block current thread for 60s and ensure the events are dispatched.
page.waitForTimeout(60_000);