如何在 Kotlin 中初始化一个线程?

65

在Java中,它通过接受实现了Runnable接口的对象来工作:

Thread myThread = new Thread(new myRunnable())

其中myRunnable是一个实现了Runnable接口的类。

但是当我在Kotlin中尝试这样做时似乎不起作用:

var myThread:Thread = myRunnable:Runnable

var myThread = Thread(myRunnable()) - Mibac
@Mibac 它成功了!你能帮我理解这段代码吗? - Shubhranshu Jain
执行 myThread:Thread 表示变量 myThread 的类型是 Thread。而执行 myRunnable:Runnable 没有任何意义。在 Kotlin 中初始化类与 Java 非常相似,只需删除 new 关键字即可。相关的 Kotlin 文档:ab - Mibac
谢谢。所以 x:X 格式适用于类,但不适用于接口? - Shubhranshu Jain
它适用于接口,但当你执行x = Y:y时,Y:y这部分没有任何意义。 - Mibac
你应该看一下这个指南,了解关于定义变量和实例的基本语法。 - BakaWaii
10个回答

84

Kotlin自带一个标准库函数thread,我建议在此处使用:

public fun thread(
    start: Boolean = true, 
    isDaemon: Boolean = false, 
    contextClassLoader: ClassLoader? = null, 
    name: String? = null, 
    priority: Int = -1, 
    block: () -> Unit): Thread

你可以像这样使用它:
thread {
    Thread.sleep(1000)
    println("test")
}

它有许多可选参数,例如通过将start设置为false来不直接启动线程。


替代方案

要初始化类Thread的实例,请调用其构造函数:

val t = Thread()

您可以将可选的Runnable作为lambda(SAM转换)传递,如下所示:
Thread {
    Thread.sleep(1000)
    println("test")
}

更明确的版本是像这样传递一个匿名的Runnable实现:
Thread(Runnable {
    Thread.sleep(1000)
    println("test")
})

请注意,先前展示的例子仅仅是创建了一个Thread实例,并没有真正地启动它。为了达到这个目的,您需要显式地调用start()方法。

4
请注意,您可以省略 start=true(因为默认情况下 starttrue),并且只需编写 thread { Thread.sleep(1000) } 即可启动线程。 - Ilya Serbis
我已添加了一条注释以使其更明显,谢谢。 - s1m0nw1

26

可运行的:

val myRunnable = runnable {

}

线程:

Thread({  
// call runnable here
  println("running from lambda: ${Thread.currentThread()}")
}).start()

在这里你看不到 Runnable:在 Kotlin 中,它可以很容易地用 lambda 表达式替换。有更好的方式吗?当然有!以下是您可以通过 Kotlin 方式实例化和启动线程的方法:

thread(start = true) {  
      println("running from thread(): ${Thread.currentThread()}")
    }

@Mibac 我提供了更多的选择。 - Rajesh Dalsaniya

13

我按照以下方式操作,看起来效果符合预期。

Thread(Runnable {
            //some method here
        }).start()

7

最好的方法是使用kotlin.concurrent中的thread()生成器函数:

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/thread.html

你应该检查它的默认值,因为它们非常有用:

thread() { /* do something */ }

请注意,与线程示例不同,您不需要调用start()或提供start=true
请注意长时间运行的线程。指定thread(isDaemon=true)很有用,以便您的应用程序能够正确终止。
通常,应用程序将等待所有非守护进程线程终止。

1
好的,简单易懂的解决方案...isDaemon是什么意思?请在您的回答中解释一下。 - Prajwal Waingankar

4

首先,创建一个用于设置默认属性的函数

fun thread(
  start: Boolean = true, 
  isDaemon: Boolean = false, 
  contextClassLoader: ClassLoader? = null, 
  name: String? = null, 
  priority: Int = -1, 
  block: () -> Unit
): Thread

然后执行调用此函数的后台操作

thread(start = true) {
     //Do background tasks...
}

或者Kotlin协程也可以用于执行后台任务。

GlobalScope.launch {

    //TODO("do background task...")
    withContext(Dispatchers.Main) {
        // TODO("Update UI")
    }
    //TODO("do background task...")
}

3

ThreadLamda的基本示例

fun main() {
    val mylamda = Thread({
        for (x in 0..10){
            Thread.sleep(200)
            println("$x")
        }
   })
    startThread(mylamda)

}

fun startThread(mylamda: Thread) {
    mylamda.start()
}

2
thread { /* your code here */ }

0
请尝试这段代码:
Thread().run { Thread.sleep(3000); }

4
"也尝试添加一些解释" - dipak_pusti
虽然这个回答可能解决了问题,但最好解释一下回答的关键部分,并可能说明一下OP的代码出了什么问题。 - pirho
3
这段代码不能解决问题:它没有启动新线程,而是在当前线程中执行 Thread.sleep(3000)(使用 Kotlin 的通用 run 扩展方法,将新创建的线程作为接收器但未执行任何操作)。 - Ilya Serbis
为了简化@IlyaSerbis的解释:这个答案不起作用。括号内的代码在当前运行的任何父线程中执行,而不是新线程。 :( - SMBiggs

0
fun main(args: Array<String>) {

    Thread({
        println("test1")
        Thread.sleep(1000)
    }).start()

    val thread = object: Thread(){
        override fun run(){
            println("test2")
            Thread.sleep(2000)
        }
    }

    thread.start()

    Thread.sleep(5000)
}

通常最好解释一下解决方案,而不仅仅是发布一些匿名代码行。您可以阅读《如何撰写良好的答案》和《解释完全基于代码的答案》。 - Anh Pham

0
在Kotlin上非常简单:
Thread {
     // your code here
}.start()

另一个例子:

val thr = Thread {
    // your code here
}
thr.start()
thr.join()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接