将Thread/Runnable实现从Java转换为Kotlin

Cra*_*tis 8 java kotlin kotlin-interop

我有一个现有的Java类ThreadUtils,其方法every如下所示:

public class ThreadUtil {

    public static Thread every(int seconds, Runnable r) {
        Thread t = new Thread(() -> {
            while(true) {
                r.run();
                try {
                    Thread.sleep(1000 * seconds);
                } catch (InterruptedException e) {
                    return;
                }
            }
        });
        t.start();
        return t;
    }
}
Run Code Online (Sandbox Code Playgroud)

而我正在尝试将其转换为Kotlin.我在Runnable关闭时有点挂了.这失败了return:

fun every(seconds: Int, r: Runnable): Thread {
    val t = Thread({
        while (true) {
            r.run()
            try {
                Thread.sleep((1000 * seconds).toLong())
            } catch (e: InterruptedException) {
                return // ERROR: This function must return a value of type Thread
            }
        }
    })
    t.start()
    return t
}
Run Code Online (Sandbox Code Playgroud)

我也尝试将Runnable拉出来帮助自己分开,但这也失败了:

fun every(seconds: Int, r: Runnable): Thread {
    val internalRunnable = Runnable {
        while (true) {
            r.run()
            try {
                Thread.sleep((1000 * seconds).toLong())
            } catch (e: InterruptedException) {
                return // ERROR: This function must return a value of type Thread
            }
        }
    }
    val t = Thread(internalRunnable)
    t.start()
    return t
}
Run Code Online (Sandbox Code Playgroud)

如何实现一个@FunctionalInterface或类似风格的闭包/ lambda,它不会尝试return 定义它的函数?

hot*_*key 10

在Kotlin中,returnlambdas中的语句与Java中的语句不同.如果你只是写return,它意味着从使用关键字声明的最内层函数返回fun,它忽略lambdas - 在你的代码中,它意味着'从every' 返回'.

要从lambda返回,请使用qualified return@label- 在您的情况下,它是return@Thread(和return@Runnable第二个示例),就像在这个简化的代码段中一样:

for (i in 1..4) {
    Thread { 
        if (i % 2 == 0)
            return@Thread
        println("Thread $i")
    }.run()
}
Run Code Online (Sandbox Code Playgroud)

(此代码的runnable演示)

此外,还有一个thread { ... }函数kotlin-stdlib,您可能会发现它很有用(同样,它的lambda的return语句也是如此return@thread).

您可以在语言参考本答案中找到更详细的说明.

  • 应该是`.start()`而不是`.run()`在不同的线程中启动。 (3认同)