#java #многопоточность #jsoup
Для онлайн-игры пишу прогу, которая позволит получать полезные данные.
Есть два метода, которые возвращают стоимость конкретного оружия на рынке для одной
страны и для всех стран (74) вместе.
public void getCheapestWeapon(Weapon weapon) {
//long result = 0;
Map countryAndId = allCountries.getCountryAndId();
for (Map.Entry item : countryAndId.entrySet()) {
//long start = System.currentTimeMillis();
getCheapestWeapon(item.getKey(), weapon);
//long finish = System.currentTimeMillis();
//System.out.println(finish - start);
//result += finish - start;
}
//System.out.println(result);
}
public void getCheapestWeapon(String country, Weapon weapon) {
long start = System.currentTimeMillis();
String link = MARKET_LINK
+ allCountries.getCountryId(country)
+ "/" + weapon.getPlaceOnMarket()
+ "/" + weapon.getQuality()
+ "/" + ADDITIONAL_LINK;
try {
Document page = Jsoup.connect(link)
.userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36")
.cookies(cookies)
.timeout(1000)
.get();
Elements table = page.getElementsByClass("price_sorted");
Element row = table.select("tr").first();
Elements columns = row.getElementsByTag("td");
Element priceCell = columns.get(3);
String priceStr = priceCell.text();
double price = Double.parseDouble(priceStr.substring(0, priceStr.length() - 4));
System.out.println(country + " - " + price);
} catch (IOException e) {
e.printStackTrace();
}
//long finish = System.currentTimeMillis();
//System.out.println(finish - start);
}
Проблема в том, что при получении данных для всех стран, время на парсинг составляет
в среднем 16-18 секунд что, согласитесь, очень много.
Пробовал в первом методе засунуть getCheapestWeapon(item.getKey(), weapon) в отдельный
поток. Ничего хорошего это не дало. Как можно реализовать одновременный парсинг всех
74-х страниц?
Ответы
Ответ 1
В текущем виде (результаты работы getCheapestWeapon просто выводятся на консоль) проще всего использовать стандартный ExecutorService public void getCheapestWeapon(Weapon weapon) { final int THREADS = 4; ExecutorService pool = Executors.newFixedThreadPool( THREADS ); MapcountryAndId = allCountries.getCountryAndId(); for (Map.Entry item : countryAndId.entrySet()) { pool.execute( () -> getCheapestWeapon( item.getKey(), weapon ) ); } pool.shutdown(); } Если операция не разовая, то нужно вынести создание и остановку сервиса из метода. Т.к. основная задержка, скорее всего из-за сети (74 запроса, даже если пакет идет от клиента до сервера 50мс, съедят 7 секунд), число процессов в сервисе может превышать количество ядер (подберите экспериментально). В качестве альтернативы, попробуйте получать у сервера больше данных меньшим количеством запросов, например убрав фильтр по странам, если вам нужна самая низкая цена.
Комментариев нет:
Отправить комментарий