Как обеспечить то же поток не повторять ввод в блок кода - PullRequest
0 голосов
/ 02 апреля 2019

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

Я хочу, чтобы каждая итерация выполнялась другим потоком.Поэтому я создал пул потоков, используя executorsservice (количество потоков совпадает с числом URL), и я использовал ключевое слово synchronized, чтобы разрешить только одному потоку одновременно выполнять блок вычислений.

Но как я могу гарантировать, чтотот же поток не будет повторно входить сначала в блок кода сноваесли потребуется, я опубликую фрагмент кода позже.

Спасибо.

Вывод, который я получаю, следующий:

Я ищу по 2 ключевым словам в каждом URL.в этом примере 1 URL и 2 ключевых слова.

Текущая тема: pool-1-thread-2 ----------------- Текущая тема: pool-1-thread-1 -----------------

Название: Wikipedia, URL бесплатной энциклопедии: https://en.wikipedia.org Ключевое слово Times Free Найдено: 41

Название: Википедия, URL бесплатной энциклопедии: https://en.wikipedia.org Ключевое слово Times Free Найдено: 41

Название: Википедия, URL бесплатной энциклопедии: https://en.wikipedia.org Ключевое слово Times найдено Wikibooks: 82

Название: Wikipedia, URL бесплатной энциклопедии: https://en.wikipedia.org Ключевые слова Times Wikibooks Найдено: 82

Я думаю, что сделал это каким-то образом, но сейчас у меня возникают новые проблемынапример, смотрите комментарии внутри метода run.

        public class KeywordCounter {

        private List keylist;
        private List weblist;

        public KeywordCounter(List keywordlist, List listWebsites) {
            this.keylist = new ArrayList(keywordlist);
            this.weblist = new ArrayList(listWebsites);

        }

        public void threadCreate(List klist, List listWebsites) {

            // TODO Auto-generated method stub

            ExecutorService executor = Executors.newFixedThreadPool(2);


            for (int w = 0; w < this.weblist.size(); w++) {

                executor.execute(new Runnable() {

                    private List keylist = new ArrayList(klist);
                    private List weblist = new ArrayList(listWebsites);

                    @Override
                    public synchronized void run() {
System.out.println("Current Thread: " + Thread.currentThread().getName().toString() + " ")

// Computations i want one thread inside here each time but i think both threads are entering same time cause i saw 4 results instaid of 2.
//Also i want inside here to pass the w variable of the for loop, cause i need it for further computations how i can achieve this?.

                });

            }

        }
    }

Ответы [ 3 ]

0 голосов
/ 02 апреля 2019

«Критический раздел»

Если у вас есть два URL, у вас будет два потока. Один поток для одного URL и другой поток для другого URL. Оба запускаются одновременно.

Теперь у нас есть кусок кода, который не должен выполняться параллельно, но весь другой код должен выполняться параллельно. Кусок кода должен быть выполнен sequientiel! Мы называем этот кусок кода «Критическим разделом».

Ключевое слово "Синхронизировано"

Чтобы пометить раздел как критический в Java, вы можете использовать синхронизированный оператор:

01 mulithread-code
02 mulithread-code
03 mulithread-code
04 synchronized {
05   critical code
06   critical code
07 }
08 mulithread-code
09 mulithread-code
10 mulithread-code

Имея два потока, первый поток, присоединяющийся к строке 04, будет запущен без задержки. Второй поток будет ждать. Первый поток выполнит всю работу от строки 05 до строки 06.

Затем происходит волшебство: как только первый поток покидает строку 07, второй поток прекращает свое ожидание и продолжает свою работу: второй поток начнет выполнять строку 05, а затем 06.

0 голосов
/ 02 апреля 2019
 import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Client2 {

    public static void main(String[] args) {


        ExecutorService pool= Executors.newFixedThreadPool(5);
        ExecutorCompletionService<String> completionService = new ExecutorCompletionService<String>(pool);

        List<String> url=Arrays.asList("www.goole.in","www.abc.com");
        for(int i=0;i<url.size();i++) {
        completionService.submit(new MyCallable(url.get(i)));
        }

        for(int i=0;i<url.size();i++) {
        try {
            Future<String> s=completionService.take();
            System.out.println(s.get());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        }
    }

}

 class MyCallable implements Callable<String>{

    String Url;
    public MyCallable(String url) {
        this.Url=url;
    }

    @Override
    public String call() throws Exception {
    //process the URL
        return Url+" Processed.";
    }

}
0 голосов
/ 02 апреля 2019

Перед некоторым кодом сложно сказать, но вы на правильном пути. Попробуйте также использовать BlockingQueue. Если у вас более 1 потока с очередью и если каждый поток работает с одним и тем же временем, вы можете быть уверены, что это не будет цикл. Конечно, если ваш поток1 работает за 1 мс, а ваш поток 2 работает за 1 минуту, так что ... без всякой блокировки.

Попробуйте использовать ждать / уведомить также

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