Java 提高基于多线程Selenium WebDriver的暴力机器人的性能

Java 提高基于多线程Selenium WebDriver的暴力机器人的性能,java,multithreading,selenium-webdriver,concurrency,webdriver,Java,Multithreading,Selenium Webdriver,Concurrency,Webdriver,各位!! 我刚刚创建了一个蛮力机器人,它使用WebDriver和多线程对4位代码进行蛮力。4位表示0000-9999个可能字符串值的范围在我的情况下,在单击“提交”按钮后,客户端从服务器获得响应的时间不少于7秒。因此,我决定使用Thread.sleep(7200)让带有响应的页面完全加载。然后,我发现我不能等待9999*7,5秒来完成任务,所以我不得不使用多线程。我有一台四核AMD机器,每1个硬件1个虚拟核,这使我有机会同时运行8个线程。好的,我已经将9999个组合的整个工作在8个线程之间平均分

各位!! 我刚刚创建了一个蛮力机器人,它使用WebDriver和多线程对4位代码进行蛮力。4位表示0000-9999个可能字符串值的范围在我的情况下,在单击“提交”按钮后,客户端从服务器获得响应的时间不少于7秒。因此,我决定使用Thread.sleep(7200)让带有响应的页面完全加载。然后,我发现我不能等待9999*7,5秒来完成任务,所以我不得不使用多线程。我有一台四核AMD机器,每1个硬件1个虚拟核,这使我有机会同时运行8个线程。好的,我已经将9999个组合的整个工作在8个线程之间平均分开,每个线程的工作范围为1249个组合+从最后开始的剩余线程。好了,<强>现在我的工作在1、5小时中完成了(因为正确的代码似乎在工作范围的中间)。这是更好的,但它可以更好!你知道,线程。睡眠(7500)纯粹是浪费时间。由于硬件核心数量有限,我的机器可能会切换到其他线程,这些线程是
wait()
。如何做到这一点?有什么想法吗

以下两个类代表了我的体系结构方法:

public class BruteforceBot extends Thread {

// All the necessary implementation, blah-blah

public void run() {
        brutforce();
    }

    private void brutforce() {
        initDriver();
        int counter = start;
        while (counter <= finish) {
            try {
                webDriver.get(gatewayURL);                
                webDriver.findElement(By.name("code")).sendKeys(codes.get(counter));              
                webDriver.findElement(By.name("code")).submit();                
                Thread.sleep(7200);
                String textFound = "";                
                try {
                    do {
                        textFound = Jsoup.parse(webDriver.getPageSource()).text();
                        //we need to be sure that the page is fully loaded
                    } while (textFound.contains("XXXXXXXXXXXXX"));
                } catch (org.openqa.selenium.JavascriptException je) {
                    System.err.println("JavascriptException: TypeError: "
                            + "document.documentElement is null");
                    continue;
                }
                // Test if the page returns XXXXXXXXXXXXX below
                if (textFound.contains("XXXXXXXXXXXXXXXx") && !textFound.contains("YYYYYYY")) {
                    System.out.println("Not " + codes.get(counter));
                    counter++;
                    // Test if the page contains "YYYYYYY" string below
                } else if (textFound.contains("YYYYYYY")) {
                    System.out.println("Correct Code is " + codes.get(counter));
                    botLogger.writeTheLogToFile("We have found it: " + textFound
                            + " ... at the code of " + codes.get(counter));
                    break;
                    // Test if any other case of response below
                } else {
                    System.out.println("WTF?");
                    botLogger.writeTheLogToFile("Strange response for code "
                            + codes.get(counter));
                    continue;
                }
            } catch (InterruptedException intrrEx) {
                System.err.println("Interrupted exception: ");
                intrrEx.printStackTrace();
            }
        }
        destroyDriver();
    } // end of bruteforce() method

好的,所以大家都等不及我的问题会得到答复,所以我决定尽快(现在!)回答。 如果您想提高基于Selenium WebDriver的暴力机器人的性能,您需要拒绝使用Selenium WebDriver。因为WebDriver在操作系统中是一个单独的进程,所以它甚至不需要JVM来运行。所以,Bot的每一个实例不仅是我的JVM管理的一个线程,也是一个Windows进程!这就是为什么当这个应用程序运行超过8个线程(每个线程都调用一个Windows进程geckodriver.exe或chromedriver.exe)时,我几乎无法使用我的电脑的原因。好的,所以要提高这种暴力机器人的性能,您真正需要做的是使用HtmlUnit而不是Selenium!HtmlUnit是一个纯Java框架,它的jar可以在Maven Central上找到,它的依赖关系可以添加到pom.xml中。这样,强制执行4位代码需要15-20分钟,考虑到每次尝试后网站的响应速度不超过7秒。相比之下,与SeleniumWebDriver相比,完成任务需要90分钟。
再次感谢@MartinJames,他指出Thread.sleep()确实可以让硬件内核切换到其他线程

线程。睡眠(7500)纯粹是浪费时间。我的机器可能正在切换到其他线程,这些线程是wait()'我不明白。如果一个线程选择Sleep(),操作系统将阻止它并释放它运行的内核。如果另一个线程准备就绪,它将“立即”调度到现在空闲的内核上。如果您的线程代码中有一个Sleep(7200)调用,那么您可以运行800个线程,没有问题,而且您不会注意到任何减速。@MartinJames,不幸的是,
Sleep()
没有释放其资源上的锁。讨论了这个问题。在Thread.sleep()期间,物理内核不会被释放,但它将执行Thread.sleep()。就我所知,只有wait()在这里有帮助。@MartinJames,你认为这是因为geckodriver.exe和chromedriver.exe都是独立的Windows程序,它们与我的Java应用几乎没有关系,占用了我的线程吗?也许,这不是一个Java多线程问题,而是一个Windows多道程序设计问题。。。无论如何,我希望得到的建议仍然有效:)“在Thread.sleep()期间,物理内核不会被释放,但它将执行Thread.sleep()。-这是完全错误的。@MartinJames,你完全正确!“如果一个线程选择Sleep(),操作系统会阻止它并释放它所运行的内核”-这是正确的!我错了——我刚刚做了一个实验,用800个线程打印A、B和C。在每个字母和“是”之间有睡眠(20000个)——所有的800个字母都是同时打印的。那么,为什么我的应用程序落后了那么多线程?是否因为Selenium WebDriver实例也是一个线程,甚至是操作系统中的一个单独进程?
   public class ThreadMaster {

// All the necessary implementation, blah-blah

        public ThreadMaster(int amountOfThreadsArgument, 
                ArrayList<String> customCodes) {
        this();
        this.codes = customCodes;
        this.amountOfThreads = amountOfThreadsArgument;        
        this.lastCodeIndex = codes.size() - 1;
        this.remainderThread = codes.size() % amountOfThreads;
        this.scopeOfWorkForASingleThread 
                = codes.size()/amountOfThreads;
    }

    public static void runThreads() {
        do {
        bots = new BruteforceBot[amountOfThreads];
        System.out.println("Bots array is populated");
    } while (bots.length != amountOfThreads);
    for (int j = 0; j <= amountOfThreads - 1;) {
        int finish = start + scopeOfWorkForASingleThread;
        try {
            bots[j] = new BruteforceBot(start, finish, codes);
        } catch (Exception e) {
            System.err.println("Putting a bot into a theads array failed");
            continue;
        }
        bots[j].start();
        start = finish;
        j++;
    }
    try {
        for (int j = 0; j <= amountOfThreads - 1; j++) {
            bots[j].join();
        }
    } catch (InterruptedException ie) {
        System.err.println("InterruptedException has occured "
                + "while a Bot was joining a thread ...");
        ie.printStackTrace();
    }
    // if there are any codes that are still remain to be tested  - 
    // this last bot/thread will take care of them 
    if (remainderThread != 0) {
        try {
            int remainderStart = lastCodeIndex - remainderThread;
            int remainderFinish = lastCodeIndex;
            BruteforceBot remainderBot
                    = new BruteforceBot(remainderStart, remainderFinish, codes);
            remainderBot.start();
            remainderBot.join();
        } catch (InterruptedException ie) {
            System.err.println("The remainder Bot has failed to "
                    + "create or start or join a thread ...");
        }
    }

}
public static void main(String[] args)
        throws InterruptedException, org.openqa.selenium.SessionNotCreatedException {
    System.setProperty("webdriver.gecko.driver", "lib/geckodriver.exe");         
    ThreadMaster tm = new ThreadMaster(8, new CodesGenerator().getListOfCodesFourDigits());     
    tm.runThreads();