Разработка универсального интерфейса асинхронной отменяемой операции - PullRequest
3 голосов
/ 12 сентября 2010

Я рассматривал универсальный / отменяемый интерфейс общего назначения для асинхронных запросов / ответов. Требования следующие, оно должно:

  • Поддержка асинхронных вызовов
  • Быть отменяемым
  • Будьте родовым
  • Запрос поддержки / ответ
  • Поддержка либо возврата в текущем потоке, либо обработки ответа в другом ответе

Итак, вот мой первый удар:

interface AsyncOperation<INPUT, OUTPUT> {
    Future<OUTPUT> execute(INPUT in, AsyncCallback<OUTPUT> callback);
}

interface AsyncCallback<OUTPUT> {
    void done(OUTPUT output);
}

Использование:

// completely async operation
operation.execute("Test", new AsyncCallback<String> {
    public void done(String output) {
        // process result...
    }
});

// sync operation with cancellation after timeout
Future<String> future = operation.execute("Test", null);
try {
    String result = future.get(1000);
} catch(TimeoutException ex) {
    future.cancel();
}

Недостатки

  • Это сложно
  • Он поддерживает только один параметр запроса - не слишком озабочен этим
  • Единое «готово» означает, что исключения должны передаваться через «готово», это можно решить с помощью onSuccess и onException (и onFinally?) В AsyncCallback, но это сделает его еще более подробным

В некоторых случаях методы сервиса Google Protocol Buffers следуют относительно схожей модели:

void [methodname](RpcController controller, 
    [RequestClass] request, RpcCallback<[ResponseClass]> callback);

Есть идеи получше?

Ответы [ 3 ]

1 голос
/ 12 сентября 2010

Вам нужен параметр типа INPUT? Разве не было бы проще, если бы объекты операций удерживали ввод как состояние, как в:

void greet(final String name) {
    new AsyncOperation<Object>() {
        @Override Object doIt() {
            System.out.println("Hello " + name + "!");
        }
    }.execute(null);
}

Таким образом, вызывающий может передать столько параметров, сколько ему нужно, безопасным способом.

Кроме того, использование обратного вызова и возвращение будущего кажется странным использованием. Вы уверены, что вам это нужно? Вы можете предоставить два метода execute, один из которых возвращает будущее, а другой вызывает обратный вызов.

0 голосов
/ 24 сентября 2010

Хорошо, отстой, чтобы ответить на ваш собственный вопрос, но я придумала набор классов, который вполне подходит для этого:

0 голосов
/ 12 сентября 2010

Взгляните на jetlang . Он поддерживает асинхронные операции и модель запрос-ответ. Вот пример из их тестов:

@Test
public void simpleRequestResponse() throws InterruptedException {
    Fiber req = new ThreadFiber();
    Fiber reply = new ThreadFiber();
    req.start();
    reply.start();
    RequestChannel<String, Integer> channel = new MemoryRequestChannel<String, Integer>();
    Callback<Request<String, Integer>> onReq = new Callback<Request<String, Integer>>() {
        public void onMessage(Request<String, Integer> message) {
            assertEquals("hello", message.getRequest());
            message.reply(1);
        }
    };
    channel.subscribe(reply, onReq);

    final CountDownLatch done = new CountDownLatch(1);
    Callback<Integer> onReply = new Callback<Integer>() {
        public void onMessage(Integer message) {
            assertEquals(1, message.intValue());
            done.countDown();
        }
    };
    AsyncRequest.withOneReply(req, channel, "hello", onReply);
    assertTrue(done.await(10, TimeUnit.SECONDS));
    req.dispose();
    reply.dispose();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...