Создание n потоков, максимум 5 активных одновременно, дождитесь завершения всех, прежде чем продолжить

#java #multithreading #swing #selenium-webdriver #java-threads

#java #многопоточность #swing #selenium-webdriver #java-потоки

Вопрос:

Я создаю веб-сканер с Selenium и шаблоном проектирования MVC на Java. Я пытаюсь добиться трех вещей:

  1. Чтобы создать n количество потоков в зависимости от длины моей базы данных (sidb), в которой хранятся настройки поиска.

  2. Поскольку в моем графическом интерфейсе есть табличная панель с данными, мне нужно, чтобы все потоки завершились, прежде чем продолжить. В противном случае я потеряю некоторые данные, потому что метод table.refresh() вызывается рано.

  3. Поскольку одновременный запуск более 5 окон Firefox слишком сильно замедлит работу моего компьютера, я бы хотел, чтобы в любой момент времени работало не более 5 потоков.

Следующий код решает первую проблему и в некоторой степени вторую. Мне пришлось создать неприятный Thread.sleep(), чтобы он не запускал обновление таблицы слишком рано.

 public void runSearchItems() {
        for (int i = 0; i < sidb.getSize(); i  ) {
            final int num = i;
            Thread tn = new Thread(new Runnable() {

                @Override
                public void run() {
                    if (sidb.getSearhItem().get(num).getFormevent().getDomainBox().equalsIgnoreCase("www.someURL.com") == true) {
                        String searchField = sidb.getSearhItem().get(num).getFormevent().getSearchField();
                        int searchCat = sidb.getSearhItem().get(num).getFormevent().getSearchCategory();
                        boolean defect = sidb.getSearhItem().get(num).getFormevent().isDefectCheck();
                        boolean region = sidb.getSearhItem().get(num).getFormevent().isRegionCheck();
                        String arrange = sidb.getSearhItem().get(num).getFormevent().getArrangeBy();
                        ArrayList<SiteData> ls = wb.searchWebSite(searchField, searchCat, defect, region, arrange);
                        for (int j = 0; j < ls.size(); j  ) {
                            db.addSiteData(ls.get(j));
                        }
                    }
                }
            });
            tn.start();
            try {
                tn.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
  

Как правильно это сделать?

Спасибо!

Комментарии:

1. Вероятно, вам следует взглянуть на пул потоков.

Ответ №1:

Небольшие изменения в вашем коде

 public void runSearchItems() { 
    List<Thread> allThreads = new ArrayList<>();


        for (int i = 0; i < sidb.getSize(); i  ) {
            final int num = i;
            Thread tn = new Thread(new Runnable() {

                @Override 
                public void run() { 
                    if (sidb.getSearhItem().get(num).getFormevent().getDomainBox().equalsIgnoreCase("www.someURL.com") == true) {
                        String searchField = sidb.getSearhItem().get(num).getFormevent().getSearchField();
                        int searchCat = sidb.getSearhItem().get(num).getFormevent().getSearchCategory();
                        boolean defect = sidb.getSearhItem().get(num).getFormevent().isDefectCheck();
                        boolean region = sidb.getSearhItem().get(num).getFormevent().isRegionCheck();
                        String arrange = sidb.getSearhItem().get(num).getFormevent().getArrangeBy();
                        ArrayList<SiteData> ls = wb.searchWebSite(searchField, searchCat, defect, region, arrange);
                        for (int j = 0; j < ls.size(); j  ) {
                            db.addSiteData(ls.get(j));
                        } 
                    } 
                } 
            }); 


            allThreads.add(tn);
        } 



        for(Thread t:allThreads)
            t.start();


        for(Thread t:allThreads)
            try { 
                t.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block 
                e.printStackTrace();
            }


    } 
  

Но да, вам лучше с пулом потоков

в качестве примера https://howtodoinjava.com/java/multi-threading/java-thread-pool-executor-example /

Комментарии:

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

2. пытался запустить 8 потоков…. кажется, что все запущено… проверено с использованием кода pastebin.com/s1mzuagq

3. Я понял это и реализовал пул потоков, спасибо!