Как обрабатывать несколько запросов URL-адресов в Java без тайм-аута, используя многопоточность?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как обрабатывать несколько запросов URL-адресов в Java без тайм-аута, используя многопоточность?

Сообщение Anonymous »

Я пытаюсь создать алгоритм, который выполняет несколько запросов URL-адресов с использованием нескольких потоков. Код работает нормально без многопоточности, но когда я добавляю несколько потоков, он работает несколько секунд, а затем начинает выдавать тайм-ауты и ошибки подтверждения SSL. Я считаю, что это может быть связано с перегрузкой системы.
Вот соответствующая часть моего кода:

Код: Выделить всё

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.LinkedList;
import java.util.List;

public class Solver {

public static LinkedList search(String start, String goal) {

ConcurrentHashMap visited = new ConcurrentHashMap();
List neighborhood = Request.getLinks(start);

var result = new AtomicReference();
var atomicFound = new AtomicBoolean(false);

List threads = new LinkedList();

for (var neighbor : neighborhood) {
var thread = new Thread(() -> {
LinkedList path = BFS(neighbor, goal, visited, atomicFound);

if (path != null) {
result.compareAndSet(null, path);
atomicFound.set(true);
}
});
threads.add(thread);
thread.start();
}

for (var thread : threads)
try {
thread.join();
} catch (Exception e) {
System.out.println(e);
return null;
}

return result.get();
}

public static LinkedList BFS(String start, String goal, ConcurrentHashMap visited,
AtomicBoolean atomicFound) {

Queue queue = new LinkedList();
HashMap path = new HashMap();

boolean found = false;

queue.add(start);

while (!queue.isEmpty()) {

if (atomicFound.get())
return null;

String current = queue.poll();

if (visited.containsKey(current))
continue;

if (current.equals(goal) || found) {
found = true;
break;
}

System.out.println("=> " + current);
List neighborhood = Request.getLinks(current);

for (String neighbor : neighborhood) {

if (visited.containsKey(neighbor) || neighbor == null)
continue;

path.putIfAbsent(neighbor, current);

if (neighbor.equals(goal)) {
found = true;
break;
}

queue.add(neighbor);
}

visited.put(current, true);
}

if (!found)
return null;

LinkedList solution = new LinkedList();
String it = goal;

while (!it.equals(start)) {
solution.addFirst(it);
it = path.get(it);
}
solution.addFirst(start);

return solution;
}
}
Функция Request.getLinks создает HTTP-запрос и анализирует HTML. Я думаю, что именно здесь начинается проблема: несколько секунд все работает нормально, но затем я начинаю получать такие ошибки, как:

Код: Выделить всё

javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
Я пробовал увеличить тайм-аут, но хост все равно разрывает соединение. Вот пример журналов, которые я получаю:

Код: Выделить всё

=> /wiki/Main_Page
javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
Failed to retrieve HTML for /wiki/Madame_Tussauds
Failed to retrieve HTML for /wiki/Aaron_Carter
Есть ли у вас какие-либо предложения о том, как сделать этот процесс более эффективным, не перегружая систему и не вызывая таймаутов?
Вот как я сейчас работаю запросы:

Код: Выделить всё

public class Request {

public static LinkedList getLinks(String link) {
LinkedList links = new LinkedList();
String html = getHtml(link);

if (html == null) {
System.out.println("Failed to retrieve HTML for " + link);
return links;
}

Pattern regex = Pattern.compile("]*?\\s+)?href=\"(/wiki/[^\"]*)\"");
Matcher matcher = regex.matcher(html);

while (matcher.find()) {
links.add(URLDecoder.decode(matcher.group(1), StandardCharsets.UTF_8));
}

return links;
}

private static String getHtml(String link) {

String urlString = "https://en.wikipedia.org" + link;
StringBuilder builder = new StringBuilder();

try {

URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(15000);
connection.setReadTimeout(15000);

try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
builder.append(inputLine);
}
}

connection.disconnect();
return builder.toString();

} catch (Exception e) {
System.out.println(e);
return null;
}
}
}
Есть ли более эффективный способ выполнить эти запросы, не перегружая систему?

Подробнее здесь: https://stackoverflow.com/questions/791 ... ithreading
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»