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