Отправить новое задание исполнителю после завершения работника - PullRequest
0 голосов
/ 30 июня 2018

Я работаю над веб-сканером, который посещает страницу и извлекает ссылку для поиска определенного домена, если он не находит его, просматривает извлеченные ссылки и повторяет их, пока не достигнет предела страницы или не найдет страницу. Я пытаюсь придумать разумную логику, чтобы бот продолжал ставить задачи в очередь после того, как он извлекает ссылки, потому что задачи выполняются быстро и недостаточно времени для отправки вновь извлеченных ссылок. Как я могу реализовать реализацию, чтобы сканер ждал, пока у него не останется больше ссылок, прежде чем завершить работу исполнителя? Я включил базовый обзор моей многопоточной реализации. Я установил максимальное количество потоков равным 3 и 10 раз отправляю example.com (домены Seed)

Spawn Thread посещает сайт и извлекает ссылки, а затем возвращает их в строку. Моя проблема в том, что я должен быть в состоянии взять эти результаты и затем поместить их в очередь. Но очередь к этому времени уже закончилась. Какие-либо предложения?

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

Обновление 2 Чтобы уточнить немного, я пытаюсь предотвратить блокировку на future.get, чтобы я мог добавить возвращаемые результаты по мере их должны быть запланированы как задачи.

            int MaxThreads = 3;
            ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(MaxThreads); // How many threads
            List<Future<String>> resultList = new ArrayList<>();// Create results list

            for (int i = 0; i < 10; i ++) {
                SpawnThread task  = new SpawnThread("example.com");// Create Tasks
                Future<String> result = executor.submit(task);//Launch tasks
                //System.out.println("Added " + CurrentNum + " to the que!");
                resultList.add(result);//Store Task Result
            }

             for(Future<String> future : resultList) //Loop through results
                {
                    String resultfinished;
                    try {
                        resultfinished = future.get();
                        System.out.println(resultfinished);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
            executor.shutdown();

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

BlockingQueue queue = new ArrayBlockingQueue(1024);
        Executor executor = Executors.newFixedThreadPool(4);
        CompletionService<List<String>> completionService = 
                 new ExecutorCompletionService<List<String>>(executor);
        List<String> pagesToVisit = new ArrayList<String>();
        Set<String> pagesVisited = new HashSet<String>();

        String SeedPage = "https://example.com/";
        String currentURL = null;

        boolean done = false;
        while(!done) {

             int listsize = pagesToVisit.size();
             if(pagesToVisit.isEmpty())
             {
                 currentURL = SeedPage;
                 pagesVisited.add(SeedPage);
                 listsize = pagesToVisit.size() + 1;
              }
             else
             {
                 currentURL = nextUrl();
             }


             for(int k = 0; k < listsize; k ++)
             {

                 completionService.submit(new Spider(currentURL,"IP","PORT" ) {
                 });
             }

              int received = 0;
              boolean errors = false;
              while(received < listsize  && !errors)
              {
                  Thread.sleep(1000);
                  Future<List<String>> resultFuture = completionService.take(); //blocks if none available
                  try
                  {
                      List<String> result = resultFuture.get();
                      pagesToVisit.addAll(result);
                      received ++; 
                  }
                  catch(Exception e)
                  {
                               //log
                            e.printStackTrace();
                            errors = true;
                  }
              }

          }

1 Ответ

0 голосов
/ 30 июня 2018

Я не уверен, правильно ли я вас понял, но

Вы можете использовать awaitTermination(); метод

public boolean awaitTermination (длительный таймаут, Блок TimeUnit) выдает InterruptedException

Блокирует выполнение всех задач после завершения работы запрос, или тайм-аут происходит, или текущий поток прерывается, что произойдет первым.

Параметры: timeout - максимальная единица времени ожидания - единица времени аргумент тайм-аута

Возвращает: true, если этот исполнитель завершен, и false, если тайм-аут истекший до окончания

Броски: InterruptedException - если прервано во время ожидания

Например

try{
executor.awaitTermination(5, TimeUnit.Seconds);
}catch(InterruptedException e)
{
// Catch block
}

Метод shutdown () не ожидает завершения потоков

Инициирует упорядоченное отключение, при котором выполняются ранее отправленные задачи, но новые задачи не принимаются Вызов не имеет никакого дополнительного эффекта, если он уже выключен. Этот метод не ожидает завершения выполнения ранее отправленных задач.

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