Как сделать рекурсивный метод многопоточным

Суть вышестоящего метода - сохранение заявки от пользователя системы, для этого нужно получить список клиентов из АПИ Битрикса, который вызывается рекурсивно в зависимости от количества клиентов (апи метод отдает данные частями, в зависимости от индекса), например: 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 шт):

Автор решения: Alexander Pavlov

Если 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

→ Ссылка