Многопоточность / параллельный запуск селена Windows - PullRequest
2 голосов
/ 06 октября 2019

В настоящее время я работаю над проектом с веб-разбором и использованием селена вместе с phantomJS.

Проект, который я написал, работает нормально, но проблема в том, что он очень медленный, поэтому я подумал, что могуввести в него многопоточность.

Я знаю, что селен не является многопоточным безопасным, и у каждого потока должен быть свой собственный веб-драйвер (просто для ясности).

Дело в том:

У меня есть массив с объектами, которые используются в URL-адресе (только его часть). В настоящее время я запускаю цикл для объектов и перехожу к драйверу с заданным xpath. , получить данные и инициализировать объект. Чтобы сделать это быстрее, я хочу создать 4 потока, где каждый поток должен:

  1. Инициализировать новый веб-драйвер

  2. Получить элемент из списка, который являетсяеще не используется.

  3. Вызов различных функций для этого объекта

Я не уверен, как мне начать создавать несколько драйверов и ставить ихвсе вместе. Как я предполагаю создать темы, которые отвечают за работу? Я читал о функции переопределения запуска и о том, что в этом месте должна быть работа, которую должен выполнять поток, но как он должен знать следующий элемент из списка для использования?

Пока у меня есть следующее:

public static class MyThread implements Runnable {
        private Objectx object
        private WebDriver driver;
        public MyThread(Objectx object){
            this.object = object;
        }
        @Override
        public void run() {
            driver = driverSettings(driver);
            driver.navigate().to("website" + object.getNumber + ".html");
            function1(object);
            function2(object);
         }
    }

И в основном методе:

        ExecutorService executor = Executors.newFixedThreadPool(4);

Теперь у меня есть список объектов

    private static List<Objectx> listOfObjects = new ArrayList<Objectx>();

Можно ли тогда использовать:

For (Objectx object : listOfObjects){
        Runnabble object.getNumber() = new MyThread(object).start()
}

Или как мне добавить все объекты для создания списка работоспособности?

1 Ответ

0 голосов
/ 06 октября 2019

Вот основные шаги.

1) Создайте пул потоков. Количество потоков не зависит от размера обрабатываемых объектов. Например, вы можете создать пул из 4 потоков для обработки 250 объектов.

2) При создании потока передать список объектов его конструктору.

3) Каждый поток принимаетСледующий объект из списка и удаляет его из списка. Вы можете использовать очередь вместо списка.

4) Важное замечание: Доступ к списку (очереди) должен быть синхронизирован, чтобы его мог изменять только один поток за раз. Один из самых простых способов - использовать ConcurrentLinkedQueue.

5) Каждый поток в run () извлекает следующую задачу из списка (из очереди), обрабатывает ее, извлекает следующую задачу. Если задач больше нет, поток завершает свой метод run ().

Обновление 1: (после обновления вопроса)

Имя «MyThread» вводит в заблуждениепотому что это не нить. Я бы посоветовал вам назвать его в соответствии с тем, что он делает, например, «WebSiteParser». Но для функционального результата это не имеет значения:)

Когда вы создали свои экземпляры runnable, вы должны отправить их исполнителю. Он будет выполнять их в соответствии с количеством потоков в пуле.

Обновление 2:

Относительно повторного использования веб-драйверов: если вы используете ExecutorService, то я бырекомендуем заранее создавать веб-драйверы, помещать их в стек или очередь. Когда поток запускает свою задачу, он должен взять веб-драйвер из этого стека или очереди. Когда он завершит свою задачу, он должен поместить свой веб-драйвер обратно в стек или очередь. Снова убедитесь, что доступ к этому стеку или очереди является потокобезопасным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...