循环阻止异步请求被形成。为什么以及如何解决?

Loop blocking asynchronous request from being beformed. Why and how to solve?

我在匿名内部 class 中定义了如何处理从我的服务器收到的响应,我将响应存储在 Map 中以允许从内部 class 外部进行访问。 因为我的服务器调用是异步的,所以我实现了一个 while 循环来等待结果被放入映射中,然后 return 它到调用函数。 但是,不知何故,我的循环没有被执行(至少据我所知),并且循环似乎阻止了我的请求完成,这显然会导致无休止的循环。

public Login getLoginByUsername(String username)
    {
        long callID = counter.incrementAndGet();
        System.out.println("Start call");
        ServerConnection.get("myURI",null, new JsonHttpResponseHandler(){
            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONObject response){
                try {

                    System.out.println("Call success, enter result:");
                    callResults.put(callID, new CallResult(Login.parseFromJson(response)));
                    System.out.println(callResults.get(callID));

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });

        System.out.println("start waiting");
       while(callResults.get(callID) == null){
            //wait
           System.out.print(".");
        }
        System.out.println("\nwaiting over, return result:");
        System.out.println(callResults.get(callID));
        return (Login) callResults.remove(callID).content;
}

我确定请求可以正常工作。如果我删除循环(并且 return null 以避免 NPE 访问尚未完成的结果),我可以从控制台输出中看到请求已执行并在函数终止后产生有效结果。

我还尝试将整个请求 (ServerConnection.get) 移动到另一个方法,以防执行异步调用的方法由于某种原因必须终止才能执行调用。这也没有帮助。

此外,我从来没有在循环中定义控制台输出,所以我怀疑它是否正确执行...

这里发生了什么,我该如何解决?

while 循环可能会最大化您的 CPU 并限制所有其他执行。在这样的等待循环中,您应该始终引入某种延迟,即使是 100-10 毫秒也足够了。

只需在循环中调用 Thread.sleep(100);(并在某处处理 InterruptedException)。

例如:

   while(callResults.get(callID) == null){
       try {
           Thread.sleep(100);
       } catch (InterruptedException e) {
           return null; // Return null or just throw a RuntimeException. You can be pretty sure that this will never be called unless your app gets closed or your thread intentionally interrupted.
       }
       System.out.print(".");
    }

由于相关 issue/question( 如果你好奇的话)更新代码后,我在我的请求周围放了一个线程:

public Login getLoginByUsername(String username)
    {
        long callID = counter.incrementAndGet();
        new Thread(new Runnable() {
            @Override
            public void run() {
                ServerConnection.get("person-login-relations?byUsername="+username,null, new JsonHttpResponseHandler(){
                    @Override
                    public void onSuccess(int statusCode, Header[] headers, JSONObject response){
                        try {
                            callResults.put(callID, new CallResult(Login.parseFromJson(response)));
                            System.out.println(callResults.get(callID));

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });


            }
        })   .start();

        while(callResults.get(callID) == null){
            //wait
        }
        return (Login) callResults.remove(callID).content;
    }

这似乎已经解决了我在这里描述的循环阻塞请求的问题。我猜这可能是因为请求或响应处理可能已由包含循环的同一线程处理,因此正在等待循环完成。不过我不完全确定,特别是因为我之前使用过异步请求,这些请求是在我无法控制的线程中处理的