Избегайте метода блокировки, чтобы сделать код асинхронным - PullRequest
0 голосов
/ 26 июня 2019

Как я могу изменить этот код, чтобы избавиться от блокировки потоков? Здесь .get() блокирует поток для получения результата из будущего. Но можно ли абсолютно избежать блокировки? Нечто подобное - один поток отправляет запросы, а другой получает ответы и реализует некоторый код. Чтобы сделать его полностью асинхронным.

Я пытался использовать CompletableFuture, но не мог этого понять. Пытался создать метод обратного вызова, но также не увенчался успехом.

byte[] sendRequest(JSONObject jsonObject, String username, String password) throws IOException, ExecutionException, InterruptedException {

          try (AsyncHttpClient client = new AsyncHttpClient()) {
            String userPassword;
            if (username != null && password != null) {
                userPassword = username + ":" + password;
            } else {
                throw new NullPointerException("Нет логина и/или пароля.");
            }

            Future future = client.preparePost(apiUrl)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Authorization", "Basic " + DatatypeConverter.printBase64Binary(userPassword.getBytes()))
                    .setBody(jsonObject.toString().getBytes())
                    .execute(getHandler());

            String response = (String) future.get();
            return response.getBytes();
        }

    }

    private AsyncCompletionHandler<String> getHandler() throws IOException {
        return new AsyncCompletionHandler<String>() {
            @Override
            public String onCompleted(Response response) throws IOException {
                return response.getResponseBody();
            }

            @Override
            public void onThrowable(Throwable t) {
            }
        };
    }

Что я ожидаю:

  1. Программа отправляет запрос в основной поток.
  2. Тогда существует своего рода обратный вызов, который ожидает ответа в альтернативная тема.
  3. Тем не менее, программа продолжает работать в главном потоке - она ​​продолжает отправлять больше запросов.
  4. Когда приходит ответ от сервера, обратный вызов от альтернативный поток ловит его и обрабатывает каким-то образом, но это не соответствует основной теме

1 Ответ

0 голосов
/ 26 июня 2019

Вы должны запустить асинхронную задачу в новом потоке (желательно с использованием ExecutorService или CompletableFuture).Передайте CallbackHandler задачам Runnable / Callable, и после завершения вызова вызовите методы-обработчики.

В качестве альтернативы, если все, что вас беспокоит, - это обработка асинхронных HTTP-запросов, я бы предложил не изобретать велосипед и вместо этого использовать существующие решения. Пример асинхронного http-клиента

Для других случаев использования вы можете следовать следующему примеру.

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone {

    public static void main (String[] args) throws java.lang.Exception {
        for (int i=0; i<10; i++) {
            new Thread(new MyRunnable(new CallbackHandler())).start();
        }
    }

    static class MyRunnable implements Runnable {

        CallbackHandler handler;

        public MyRunnable(CallbackHandler handler) {
            this.handler = handler;
        }

        public void run() {
            try {
                Thread.sleep(100);
            } catch(Exception e) {
            } finally {
                Random r = new Random();
                if (r.nextBoolean()) {
                    handler.onSuccess();
                } else {
                    handler.onError();
                }
            }
        }
    }

    static class CallbackHandler {
        public void onSuccess() {
            System.out.println("Success");
        }

        public void onError() {
            System.out.println("Error");
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...