首页 > 解决方案 > 避免阻塞方法使代码异步

问题描述

如何更改此代码以摆脱线程阻塞?这里.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. 当来自服务器的响应到来时,来自备用线程的回调会捕获它并以某种方式进行处理,但它与主线程不对应

标签: javaasynchronousclient-server

解决方案


您应该在新线程中运行异步任务(最好使用 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");
        }
    }
}

推荐阅读