用于处理Java中的异步响应的设计模式

Ray*_*non 17 java asynchronous response request

我从类似的问答中读到了答案

如何在JAVA中创建异步HTTP请求?| 异步编程设计模式 |
AsyncTask Android - 设计模式和返回值

我看到很多解决方案,但没有一个真的让我满意.

倾听者的方式

捕获结果后,处理将在onResult方法中实现.

public interface GeolocationListener {
public void onResult(Address[] addresses);
public void onError(Exception e);
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案并不能让我满意,因为我想在main方法中处理结果.我讨厌这个接口,因为当返回响应时,它会在onResult中处理,导致处理链,无法返回"main"方法.

servlet的方式

public class SignGuestbookServlet extends HttpServlet {

    public void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws IOException {
        // ...
        resp.sendRedirect("/guestbook.jsp");
    }
}
Run Code Online (Sandbox Code Playgroud)

没有公开的Java代码调用servlet.所有配置都在web.xml中完成

我想要的方式

等待这样的回复

Response a = getResponse();
// wait until the response is received, do not go further
// process
Response b = getResponse();
// wait until the response is received, do not go further
process(a,b);
Run Code Online (Sandbox Code Playgroud)

是否有设计模式来处理异步请求并等待上面的响应?其他方式比听众.请不要图书馆或框架.

编辑 感谢到目前为止的回复.我没有给你全部图片所以我暴露了Geolocation类我开始实现.我不知道如何实现该方法.有人能说"怎么样"?他(或她)还必须实现侦听器以检索结果

private Address getFullAddress (String text, AddressListener listener, ... ){

    // new Geolocation(text, listener, options).start() 
    // implements Geolocation.GeolocationListener   
    // how to return the Address from the onResult ?
}
Run Code Online (Sandbox Code Playgroud)

tot*_*to2 11

首先,您不应该拒绝您讨论的前两种方法.人们使用这些技术有很好的理由,你应该尝试学习它们而不是创造新技术.

否则,你应该看看java.util.concurrent:

ExecutorService es = Executors.newFixedThreadPool(2);
...
Future<Response> responseA = es.submit(responseGetter);
Future<Response> responseB = es.submit(responseGetter);

process(responseA.get(), responseB.get());
Run Code Online (Sandbox Code Playgroud)

where responseGetter是类型Callable<Response>(您必须实现该方法public Response call()).


Rya*_*art 9

异步代码始终可以同步.最简单/最原始的方法是进行异步调用,然后输入一个只停留当前线程的while循环,直到值返回.

编辑:将异步回调转换为同步代码的代码 - 再次,粗略的实现:

import java.util.concurrent.*;

public class MakeAsynchronousCodeSynchronous {
    public static void main(String[] args) throws Exception {
        final Listener listener = new Listener();
        Runnable delayedTask = new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    throw new IllegalStateException("Shouldn't be interrupted", e);
                }
                listener.onResult(123);

            }
        };
        System.out.println(System.currentTimeMillis() + ": Starting task");
        Executors.newSingleThreadExecutor().submit(delayedTask);
        System.out.println(System.currentTimeMillis() + ": Waiting for task to finish");
        while (!listener.isDone()) {
            Thread.sleep(100);
        }
        System.out.println(System.currentTimeMillis() + ": Task finished; result=" + listener.getResult());
    }

    private static class Listener {
        private Integer result;
        private boolean done;

        public void onResult(Integer result) {
            this.result = result;
            this.done = true;
        }

        public boolean isDone() {
            return done;
        }

        public Integer getResult() {
            return result;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你也可以按照hakon的回答推荐使用CountDownLatch.它基本上会做同样的事情.我还建议你熟悉java.util.concurrent包,以便更好地管理线程.最后,仅仅因为你可以做到这一点并不是一个好主意.如果您正在使用基于异步回调的框架,那么学习如何有效地使用框架比尝试颠覆它更好.


hak*_*kon 6

可以CountDownLatch帮你?在main方法中,调用getResponse,然后调用countDownLatch.await().将倒计时锁存器传递给getResponse方法,然后在getResponse中倒计时getResponse的结果完成:

CountDownLatch latch = new CountDownLatch(1);
Response a = getResponse(latch);
latch.await();

latch = new CountDownLatch(1);
Response b = getResponse(latch);
latch.await();

process(a, b);
Run Code Online (Sandbox Code Playgroud)

一旦异步部分返回结果,你的getResponse就需要调用latch.countDown().

例如:

public Response getResponse(CountDownLatch latch) {
     someAsychBloc(final CountDownLatch latch) {
       do work
       latch.countDown();
    }
}
Run Code Online (Sandbox Code Playgroud)