【问题标题】:Why `break label` cannot be used inside lambda expression? Any workaround?为什么 `break label` 不能在 lambda 表达式中使用?任何解决方法?
【发布时间】:2019-11-14 18:42:47
【问题描述】:

我正在尝试使用 HTTPClient 库为 HTTP 请求实现重试机制。对于重试机制,我有一个要尝试的网站列表,我会尝试每个网站retries 次。当我收到来自任何请求的status 200 时,该过程结束。

我的想法是使用布尔值requestSuccess 和标签requestLabel。当我收到status 200 时,我将设置requestSuccess = true 并打破requestLabel。但是,变量必须是 (effectively) final 并且 break 标签在 lambda 表达式中不可用。

是否有任何变通方法来实现这种重试机制?

boolean requestSuccess = false;

requestLabel: 
for(String site: sites) {
    for(int i = 0; i < retries; i++) {
        client.request(site, data, requestOptions, (err, res, content) -> {
            if(err == null) {
                requestSuccess = true;
                break requestLabel;
            } else {
                log(...);
            }
        })
    }
}

if(!requestSuccess) {
    log("request failed");
}


一个可能的答案

受提交然后删除的答案的启发,我可以使用类似包装类的解决方案。我认为它会起作用,但它看起来很脏?

boolean[] requestSuccess = new boolean[1];

requestLabel:
for(String site: sites) {
    for(int i = 0; i < retries; i++) {
        if(requestSuccess[0] == true) {
            break requestLabel;
        }

        client.request(site, data, requestOptions, (err, res, content) -> {
            if(err == null) {
                requestSuccess[0] = true;
            } else {
                log(...);
            }
        })
    }
}

if(!requestSuccess) {
    log("request failed");
}

【问题讨论】:

    标签: java asynchronous lambda httpclient netty


    【解决方案1】:

    一个 lambda 在引擎盖下变成了它自己的类。就 java 解释器而言,就好像你有两个类。

    class Main {
        public void runstuff() {
            labelX:
            for(...) {
                client.request(new Main$Foo().xyz(.....));
            }
        }
    
        class Foo {
             public xyz(....) {
                 break labelX; // There is no labelX to break to here in Foo.xyz
             }
        }
    }
    

    【讨论】:

    • @Andyk。如果我理解正确,如果请求在其中一个站点上匹配,您希望该站点处理它,对吗?在您当前的设置中,您正在做一个好运的方法并浪费了许多资源。如果您有 20 个不匹配的站点,如果幸运的话,您有 20 404 个。我建议你先过滤掉这些网站。然后在适当的站点上尝试请求。您使用的是哪个 http 库?
    • 感谢您的回复。该代码用于反向代理,它接受请求并重定向到另一个位置。所以我确实希望该请求在大多数情况下都能正常工作,但如果没有,我必须重试。我想到了一个可能的答案。你能看看吗(在问题中更新)?
    • 编译器不会报错。由于 arr 是一个数组对象,当我在 lambda 中执行 arr[0] = true 时,arr(引用)的值不会改变。
    • 嗯,没错,只要数组不变就行。
    猜你喜欢
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    相关资源
    最近更新 更多