Как сделать рекурсивный метод многопоточным
Суть вышестоящего метода - сохранение заявки от пользователя системы, для этого нужно получить список клиентов из АПИ Битрикса, который вызывается рекурсивно в зависимости от количества клиентов (апи метод отдает данные частями, в зависимости от индекса), например: https://N.bitrix24.ru/rest/65/TOKEN/crm.company.list.json?start=NUMBER
При первоначальном вызове number = null, поэтому старт идет с первого клиента, после запроса в ответе (JSON) содержится ключ 'next', в котором указан индекс для следующей части данных и запрос уже имеет следующий URL: https://N.bitrix24.ru/rest/65/TOKEN/crm.company.list.json?start=50
В данный момент метод выглядит так:
@Override
public List<BitrixCompany> getBitrixClients(Integer start, List<BitrixCompany> clients){
String url = REST_BITRIX24_URL + OUTER_REQUEST_TOKEN + "/crm.company.list.json?start="+start;
try{
String response = getBitrixResponse(new URL(url), "");
try (JsonReader jsonReader = Json.createReader(new StringReader(response))) {
JsonObject object = jsonReader.readObject();
object.getJsonArray("result").forEach(cl -> {
AbstractMap valuesMap = (AbstractMap) cl;
BitrixCompany client = new BitrixCompany();
client.setCompanyId(Integer.valueOf(valuesMap.get("ID").toString().replace("\"", "")));
client.setTitle(valuesMap.get("TITLE").toString().replace("\"", ""));
clients.add(client);
});
if(object.get("next") != null)
getBitrixClients(object.getInt("next"), clients);
}
} catch (IOException e) {
logger.error("Exception in getBitrixClients function is: " + e.getLocalizedMessage(), e);
}
return clients;
}
И также есть непосредственный его вызов, результатом которого является список.
Вопрос - как ускорить "сборку" данного списка, используя многопоточность (порядок не важен)? В моем дилетантском понимании это выглядит так - вызывать N раз метод (без рекурсии), при каждом n + 1 разе увеличивать переменную start на 50, чтобы собирать разные части списка, но нет идей возможно ли это сделать и как.
Ответы (1 шт):
Если next невозможно предсказать, то многопоточность тут плохо поможет.
Ещё рекурсия тут вообще не нужна
@Override
public List<BitrixCompany> getBitrixClients(Integer start, List<BitrixCompany> clients){
while (true) {
String url = REST_BITRIX24_URL + OUTER_REQUEST_TOKEN + "/crm.company.list.json?start="+start;
try{
String response = getBitrixResponse(new URL(url), "");
try (JsonReader jsonReader = Json.createReader(new StringReader(response))) {
JsonObject object = jsonReader.readObject();
object.getJsonArray("result").forEach(cl -> {
AbstractMap valuesMap = (AbstractMap) cl;
BitrixCompany client = new BitrixCompany();
client.setCompanyId(Integer.valueOf(valuesMap.get("ID").toString().replace("\"", "")));
client.setTitle(valuesMap.get("TITLE").toString().replace("\"", ""));
clients.add(client);
});
if(object.get("next") == null) return clients;
start = object.getInt("next");
}
} catch (IOException e) {
logger.error("Exception in getBitrixClients function is: " + e.getLocalizedMessage(), e);
return clients;
}
}
}
А вот если размер возвращаемой страницы всегда известен (например, 50) или ещё лучше может быть передан как параметр (например, start=null&pageSzie=50), то тогда можно распараллеливать. Например, если 2 потока, то они могут грузить
1: start=null, start=100, start=200
2: start=50, start=150, start=250
пока не каждый из них не получит next=null