等待lambda完成的正确方法

时间:2019-07-24 16:43:32

标签: java

我遇到了以下代码段:

AmqpConnection connection;
AmqpClient client = AmqpClient.create(someOptions);

client.connect(ar -> {
  if (ar.failed()) {
    System.out.println("Connection failed.");
  } else {
    System.out.println("Connection succeeded");
    connection = ar.result();
  }
});

// Wait for connection to succeed before moving on...
connection.doSomething() //etc...

我想使用它,但是需要一种阻塞机制,因此连接不为空。我不想在lambda中移动connection.doSomething()。 在这种情况下进行屏蔽的正确方法是什么?带计时器的while循环?未来/可致电?还有吗?

1 个答案:

答案 0 :(得分:2)

未来是一种好方法,但是connect返回一个吗?

您说您不想这样做,但是另一种选择是将其全部添加到lambda本身-如果您仍在等待,为什么不一起做呢?

我认为您现在设置的方式不是一个好方法,因为lambda不应影响其体外的变量(我相信您会在此上收到编译错误)。

还有更多使用java.util.concurrent的方法,但是我认为这2种是最好的。


编辑

在注释中进行讨论之后,并弄清该连接是线程安全的,您可以拆分为创建连接的ConnectionUtil(仅一次),并拆分为ConnectionUsage作为用法示例:

public class ConnectionUtil {

    private static AmqpConnection connection;

    private static Lock lock = new ReentrantLock();

    public static AmqpConnection getConnection() {
        if (connection == null) {
            lock.lock();
            if (connection == null) {
                AmqpClient client = AmqpClient.create(someOptions);
                client.connect(ar -> {
                    if (ar.failed()) {
                        System.out.println("Connection failed.");
                    } else {
                        System.out.println("Connection succeeded");
                        connection = ar.result();
                    }
                });
            }
            lock.unlock();
        }
        return connection;
    }

    public static <T> T doWithConnection(Function<AmqpConnection, T> function) {
        return function.apply(getConnection());
    }
}

对于用法,您有2种选择-如果可以通过AmqpConnection,则可以调用getConnection,如果尚未准备好lambda并将其传递给doWithConnection

public class ConnectionUsage {

    public static void main(String[] args) {
        // you can get the connection and do stuff
        AmqpConnection connection = ConnectionUtil.getConnection();


        // you can call the util and let him do stuff
        Function<AmqpConnection, Void> func = amqpConnection -> {
            // do stuff
            return null;
        };
        ConnectionUtil.doWithConnection(func);
    }
}