Есть ли лучший способ вызвать параллельный API в Java? - PullRequest
0 голосов
/ 08 октября 2019

Я звоню четырем API, используя Callable интерфейс java.util.concurrent с Java8. Я хочу сделать несколько вызовов покоя, объединить результаты и вернуть JSON. Я получаю желаемый результат, но мне нужно знать, есть ли у них лучший или чистый способ сделать это. Ниже мой код. Я хотел знать, какая часть выполняется параллельно, а какая - последовательно?

Callable<List<Map<String, Object>>> callable1 = new Callable<List<Map<String, Object>>>()
        {
            @Override
            public List<Map<String, Object>> call() throws Exception
            {  
                return aClient.get();
            }
        };

        Callable<List<Map<String, Object>>> callable2 = new Callable<List<Map<String, Object>>>()
        {
            @Override
            public List<Map<String, Object>> call() throws Exception
            {
                return bClient.get();
            }
        };

        Callable<List<Map<String, Object>>> callable3 = new Callable<List<Map<String, Object>>>()
        {
            @Override
            public List<Map<String, Object>> call() throws Exception
            {
                return cClient.get();
            }
        };

        Callable<List<Map<String, Object>>> callable4 = new Callable<List<Map<String, Object>>>()
        {
            @Override
            public List<Map<String, Object>> call() throws Exception
            {
                return dClient.get()
            }
        };

        ExecutorService executor = Executors.newFixedThreadPool(6);
        Future<List<Map<String, Object>>> future1 = executor.submit(callable1);
        Future<List<Map<String, Object>>> future2 = executor.submit(callable2);
        Future<List<Map<String, Object>>> future3 = executor.submit(callable3);
        Future<List<Map<String, Object>>> future4 = executor.submit(callable4);



        Map<String, Map<String, Object>> lists = new HashMap<>();
        try {
            putResult(future1, lists);
            putResult(future2, lists);
            putResult(future3, lists);
            putResult(future4, lists);
        } catch(InterruptedException e) {
            e.printStackTrace();
        } catch(ExecutionException e) {
            e.printStackTrace();
        }
        return metrics;
    }

    private void putResult(Future<List<Map<String, Object>>> future, Map<String, Map<String, Object>> ans) throws InterruptedException, ExecutionException {
        if(future.get() != null && future.get().size() > 0) {
            for (Map<String, Object> maps : future.get()) {
                if (maps != null && maps.containsKey("abcd")) {
                    String abcd = maps.get("abcd").toString();
                    if(!ans.containsKey(abcd))
                        ans.put(maps.get("abcd").toString(), maps);
                    else {
                        for (Map.Entry<String, Object> entry: maps.entrySet()) {
                            ans.get(abcd).put(entry.getKey(), entry.getValue());
                        }
                    }
                }
            }
        }
    }
{ 
   {
    "abcd": 1,
    "cde": 2
   },
   { 
    "abcd": 2,
     "cde": 3
   }
}

изменено на

{
   "1" : {
    "abcd": 1,
    "cde": 2
   },
   "2":{ 
    "abcd": 2,
     "cde": 3
   }

}

в функции разбора. Пожалуйста, было бы лучше сделать это в RxJava? Также скажите мне, как мы можем реализовать вышеупомянутый код в CompletableFutures?

1 Ответ

0 голосов
/ 08 октября 2019

Если вы используете Java 8+, вы можете использовать лямбда-выражения для значительного сокращения кода.

Это:

Callable<List<Map<String, Object>>> callable3 = new Callable<List<Map<String, Object>>>()
{
    @Override
    public List<Map<String, Object>> call() throws Exception
    {
        return cClient.get();
    }
};
Future<List<Map<String, Object>>> future3 = executor.submit(callable3);

Можно сократить до этого:

Future<List<Map<String, Object>>> future3 = executor.submit(cClient::get);

Я хотел знать, какая часть выполняется параллельно, а какая - последовательно?

Подготовка вызываемых элементов последовательная. Выполнение каждого из них выполняется исполнителем параллельно. Однако код синтаксического анализа снова является последовательным, хотя вы его нам не показали, поэтому я не уверен. Вы также можете распараллелить его, используя future3.thenAccept(/*call to parsing method*/) или аналогичную функцию, чтобы поток, выполнивший вызов API, проанализировал ответ, как только это будет сделано. Это должно немного повысить производительность по сравнению с реализацией, в которой рабочие потоки просто возвращают результаты, которые затем анализируются одним потоком.

...