在保持线性可读性的同时委托线程

时间:2016-04-28 13:57:01

标签: java multithreading asynchronous completable-future

我一直在尝试不同的方法来处理断开连接结果的阻塞方法,同时保持可能已被中断的状态。我发现不得不处理不同的类和方法,使发送和接收难以对齐,这令人沮丧。

在以下示例中,SomeBlockingMethod()通常会返回void,因为消息会发送到其他某个进程。但我改为使用一个接收结果的监听器synchronized。通过将其旋转到一个线程,我可以wait()结果超时或无限期。

这很好,因为一旦返回结果,我就可以继续使用一个特定的状态,我必须在等待线程任务的结果时暂停。

我的方法有什么问题吗?

虽然这个问题看起来很通用,但我特意在 Java 中寻找有关线程的建议。

伪代码示例:

public class SomeClass implements Command {

@Override
public void onCommand() {
   Object stateObject = new SomeObjectWithState();

   // Do things with stateObject

   Runnable rasync = () -> {
      Object r = SomeBlockingMethod();

      // Blocking method timed out
      if (r == null)
         return;

      Runnable rsync = () -> {
         // Continue operation on r which must be done synchronously

         // Also do things with stateObject
      };

      Scheduler().run(rsync);
   };

   Scheduler().run(rasync);
}

使用CompletableFuture进行更新:

CompletableFuture<Object> f = CompletableFuture.supplyAsync(() -> {
   return SomeBlockingMethod();
});

f.thenRun(() -> { () -> {
   String r = null;

   try {
      r = f.get();
   }
   catch (Exception e) {
      e.printStackTrace();
   }

   // Continue but done asynchronously
});

或更好:

CompletableFuture.supplyAsync(() -> {
   return SomeBlockingMethod();
}).thenAccept((
   Object r) -> {

   // Continue but done asynchronously
});

严格使用CompletableFuture的问题是CompletableFuture.thenAccept是从全局线程池运行的,并不保证与调用线程同步。

为同步任务添加调度程序修复了此问题:

CompletableFuture.supplyAsync(() -> {
   return SomeBlockingMethod();
}).thenAccept((
   Object r) -> {

   Runnable rsync = () -> {
      // Continue operation on r which must be done synchronously
   };

   Scheduler().run(rsync);
});

与完整的调度程序方法相比,使用CompletableFuture的一个警告是,任何先前存在于外部的状态必须是最终的或有效的最终状态。

1 个答案:

答案 0 :(得分:0)

您应该查看RxJava,它使用流操作并具有线程支持。

api.getPeople()
  .observeOn(Schedulers.computation())
  .filter(p -> return p.isEmployee();)
  .map(p -> return String.format("%s %s - %s", p.firstName(), p.lastName(), p.payrollNumber());)
  .toList()
  .observerOn(<ui scheudler>)
  .subscirbe(p -> screen.setEmployees(p);)