Kotlin(一)掌握基础知识:数据、集合、库函数
Kotlin(二)掌握基础知识:字符串和异常处理
Kotlin(三)掌握基础知识:类
线程是每一种语音不可能绕开的知识点,这章我们就来仔细看下Kotlin中如何使用线程,我们仔细看下Thread.kt文件的实现
package kotlin.concurrent
public fun thread(
start: Boolean = true,
isDaemon: Boolean = false,
contextClassLoader: ClassLoader? = null,
name: String? = null,
priority: Int = -1,
block: () -> Unit
): Thread {
val thread = object : Thread() {
public override fun run() {
block()
}
}
if (isDaemon)
thread.isDaemon = true
if (priority > 0)
thread.priority = priority
if (name != null)
thread.name = name
if (contextClassLoader != null)
thread.contextClassLoader = contextClassLoader
if (start)
thread.start()
return thread
}
@kotlin.internal.InlineOnly
public inline fun <T : Any> ThreadLocal<T>.getOrSet(default: () -> T): T {
return get() ?: default().also(this::set)
}
在包kotlin.concurrent中定义了两个方法
- thread
- getOrSet
其中thread方法便是我们创建线程所需要用到的函数;这个函数有6个参数,分别表示:
- 第4行,start:默认为true,表示立即运行
- 第5行,isDaemon: 默认为false,表示不是守护线程
- 第6行,contextClassLoader: 表示在这个线程中加载类/资源的类加载器
- 第7行,name:表示线程的名字
- 第8行,priority:表示线程的优先级
- 第9行,block:表示线程运行的主函数体
那thread函数返回类型是什么?看下第10行,答案是Thread类,看下这个Thread的实现
public
class Thread implements Runnable
原来Kotlin中的线程其内部实现也是java中的Thread,那么他的线程的状态,线程的终止等等肯定都符合java的标准了
从第11行到27行,就是thread方法的函数体了
那第9行中的block既然表示线程运行的主函数体,那它是怎么被执行的? 为了知晓这个问题的答案,我们首先得了解lambdar表达式
lambdar表达式一般当参数类型是一个函数的时候,就可以使用它来简化代码的编写 (高阶函数的含义为:一个将另一个函数作为参数或者返回值的函数)
其完整语法为:
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
其含义为:
定义一个变量sum,其类型是lambda表达式
位于->的左边,(Int, Int)为lambda表达式的参数,分别为两个整形,
位于->的右边,Int表示lambda表达式的返回类型
{}表示lambda的函数体
在kotlin中,如果参数如果函数的最后一个参数是函数,那么作为相应参数传入的 lambda 表达式可以放在圆括号之外,我们称之为拖尾 lambda 表达式
val product = items.fold(1) { acc, e -> acc * e }
在kotlin中,如果函数只有lambda表达式,则调用的时候,可以省略圆括号
val product = items.fold { acc, e -> acc * e }
在kotlin中,如果lambda表达式只有一个参数,则可以使用it来代替该参数,并忽略->符号
var lists = listOf("","s")
lists.forEach { print(it) }
/** 等价写法 **/
lists.forEach { it -> print(it) }
lambda表达式语法如下
1. 无参数
val/var 变量名 = { 操作的代码 }
2. 有参数
val/var 变量名 : (参数的类型,参数类型,...) -> 返回值类型 = {参数1,参数2,... -> 操作参数的代码 }
当表达式的返回值类型可以由系统自己推导出来,则可以简写为
val/var 变量名 = { 参数1 : 类型,参数2 : 类型, ... -> 操作参数的代码 }
3. lambda表达式作为函数中的参数
fun say(a : Int, 参数名 : (参数1 : 类型,参数2 : 类型, ... ) -> 表达式返回类型){
参数名() 调用该lambda表达式
}
lambda表达式实际用例:
package com.kotline.learning
private fun say() {
println("**say**")
}
private fun people(hello: () -> Unit) {
hello()
}
private fun people(content: String, hello: () -> Unit) {
println("**people**$content")
}
fun main (args: Array<String>): Unit{
people{say()}
people("content", { say() })
people("content") { say() }
}
第3行定义了一个函数say,没有参数,没有返回值/或者说返回值为Unit
第7行定义了一个函数people,其参数为hello,类型为一个lambda表达式
第8行表示调用/执行这个lambda表达式
第11行定义了一个函数people,其参数为content和hello,类型一个是字符串型,一个lambda表达式
综上内容,当我们调用函数people的时候,就可以写为
/** 调用第7行的people方法 **/
people({say()})
因为kotlin的提出原则,上面的代码可以简写为:
people(){say()}
也可以简写为
people{say()}
现在我们返回到线程方法thread的第六个参数:block
block: () -> Unit
他表示一个lambda表示式,无参且返回类型为Unit,调用函数的写法为:
block()
所以在函数thread的函数体中,即第13行,run方法中会调用到block
现在我们来看看如果通过thread方法来创建一个立即运行的线程
fun printJob() {
println("**printJob**")
}
thread({
printJob()
})
/** 可简写为: **/
thread{
printJob()
}
通过对象表达式创建一个线程
Thread(object: Runnable{
override fun run() {
}
}).start();
/** IDE会提示修改为lambda形式:**/
Thread(Runnable {
printJob()
}).start();
继承Thread类,非匿名内部类的方式实现
var kotlinThread : KotlinThread = KotlinThread();
kotlinThread.start();
class KotlinThread : Thread() {
override fun run() {
super.run()
println("KotlinThread 开始运行")
}
}