@artemfisher

Почему при параллельном выполнении кода выдается меньше результатов чем при последовательном?

Добрый день.

Парсю страницу, на которой 30 фильмов.
Потом поочердно парсю страницу каждого фильма следующим методом:

static Film GetFilm(int id) throws URISyntaxException, InterruptedException, IOException, LoaderException
	{
		URI uri = new URI("https://www.ivi.ru/watch/"+id);
		HttpClient client = HttpClient.newBuilder().followRedirects(Redirect.NORMAL).build();
		HttpRequest request = HttpRequest.newBuilder().uri(uri).GET().build();
		HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
		
		Pattern pattern = Pattern.compile(
				"<div\\sclass=\"contentCard__info\">.*?"
				+ "<h1\\sclass=\"watchTitle__title.*?\">(.*?)</h1></div>" // 1 - name
				+ "<div.*?class=\"watchParams\\scontentCard__watchParams\">"
				+ "<ul.*?class=\"watchParams__paramsList\">"
				+ "<div.*?class=\"watchParams__item\">"
				+ "<a.*?>(.*?)</a></div>" // 2 - year
				+ "<div.*?class=\"watchParams__item\">"
				+ "<a.*?data-test=\"content-duration\".*?>"
				+ "(.*?)</a></div>"  // 3 - duration
				+ "<div.*?class=\"watchParams__item\">"
				+ "<a.*?>(.*?)</a></div>" // 4 - ageCategory
				+ "</ul>"
				+ "<ul.*?class=\"watchParams__paramsList\">"
				+ "<div.*?class=\"watchParams__item\\s+watchParams__item_hasDot\">"
				+ "<a.*?>(.*?)</a></div>" // 5 - country
				+ "<div.*?class=\"watchParams__item\\s+watchParams__item_hasDot\">"
				+ "<a.*?>(.*?)</a></div>" // 6 - category					
				);		
					
		Matcher matcher = pattern.matcher(response.body());
				
		if(!matcher.find()) return null;
		
		System.out.println(Thread.currentThread().getName()+" yes get film:"+id);
					
		Pattern pattern2 = Pattern.compile("(\\d+)");
		Matcher matcher2 = pattern2.matcher(matcher.group(3));		
			
		if(!matcher2.find()) throw new LoaderException("Cannot parse the duration");		
		int duration = Integer.parseInt(matcher2.group(1))*60+Integer.parseInt(matcher.group(2)); // hours and mins to mins
		
		Matcher matcher3 = pattern2.matcher(matcher.group(4));
		
		if(!matcher3.find()) throw new LoaderException("Cannot parse age category");
		int ageCategory = Integer.parseInt(matcher3.group(1));
						
		Film film = new Film();
		
		film.SetName(matcher.group(1));
		film.SetYear(Integer.parseInt(matcher.group(2)));		
		film.SetDuration(duration);
		film.SetAgeCategory(ageCategory);
		film.SetCountry(matcher.group(5));
		film.SetCategory(matcher.group(6));		
		
		return film;		
									
	}


Вызываю данный код последовательно:
List<Integer> filmsIds = new ArrayList<>();
				
		String address = "https://www.ivi.ru/collections/movies-highrated";
		filmsIds.addAll(Loader.GetFilmList(address));	
					
		List<Film> films = new ArrayList<>();
		for(int id:filmsIds)
		{
			films.add(Loader.GetFilm(id));
		}
		
		System.out.println(films.size());


Выдает, что распарсил все 30 фильмов.

Вызываю этот метод параллельно:
List<Integer> filmsIds = new ArrayList<>();		
		
		String address = "https://www.ivi.ru/collections/movies-highrated";
		filmsIds.addAll(Loader.GetFilmList(address));	

List<Callable<Film>> tasks = new ArrayList<Callable<Film>>();
						
		for(int id:filmsIds)
		{			
			Callable<Film> task = ()->Loader.GetFilm(id);
			tasks.add(task);
		}
				
		ExecutorService executor = Executors.newCachedThreadPool();
						
		List<Future<Film>> results = executor.invokeAll(tasks);
					
		for(var res:results)
		{
			if(res.get()!=null)
			System.out.println(res.get().getName());
		}


Выдает, что распарсил 25 фильмов.

В чем причина?

Если указать в функции, в случае невозможности распарсить фильм выдавать ошибку, а не null как сейчас, то при параллельном вычислении выдает ошибку, а при последовательном нет.

UPD: при параллельном парсинге срабатывает условие if(!matcher.find()) return null; (раньше там делал выброс ошибки, но тогда обрывается выполнение остальных потоков)
Но срабатывает не на всех фильмах, примерно 25 (из 30) штук парсятся.
При последовательном выполнении парсятся все.
  • Вопрос задан
  • 95 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы