📜  kotlin 线程 - Kotlin (1)

📅  最后修改于: 2023-12-03 15:32:31.187000             🧑  作者: Mango

Kotlin 线程

Kotlin 是一门运行在 JVM 上的编程语言,因此它也继承了 Java 的线程模型。

Kotlin 为线程编程提供了方便的 API,并且通过协程的支持,也使得异步编程更加简单。

创建线程

在 Kotlin 中,可以通过 thread 函数来创建新线程。

import kotlin.concurrent.thread

fun main() {
    thread {
        // 开始执行的代码
    }
}

thread 函数接受一个 Lambda 表达式作为线程的执行体。

该函数还可以接受一个名为 name 的可选参数,指定线程的名称。

另外,thread 函数还有一个重载版本,可以接受一个 Runnable 对象作为线程的执行体。

import kotlin.concurrent.thread

fun main() {
    thread(Runnable {
        // 开始执行的代码
    })
}
线程的安全问题

由于多个线程之间共享资源,因此可能会出现线程安全的问题。

Kotlin 提供了一些工具来帮助我们避免这些问题。

Synchronized

synchronized 关键字可以将一段代码块标记为临界区(critical section),同一时间只有一个线程可以进入该块执行。

class Counter {
    private var count = 0

    // 使用 synchronized 关键字保证 count 的线程安全
    @Synchronized
    fun inc() {
        count++
    }

    fun get() = count
}

fun main() {
    val counter = Counter()
    (1..1000).forEach {
        thread {
            counter.inc()
        }
    }
    Thread.sleep(1000)
    println(counter.get()) // 1000
}
Atomic

Atomic 类提供了原子操作,可以保证对于单个操作的执行不会被其他线程打断。

import java.util.concurrent.atomic.AtomicInteger

class Counter {
    private var count = AtomicInteger(0)

    fun inc() {
        count.getAndIncrement()
    }

    fun get() = count.get()
}

fun main() {
    val counter = Counter()
    (1..1000).forEach {
        thread {
            counter.inc()
        }
    }
    Thread.sleep(1000)
    println(counter.get()) // 1000
}
Volatile

volatile 关键字可以保证线程之间对变量的修改可见,并且禁止 CPU 缓存这个变量的值。

@Volatile
var stop = false

fun main() {
    thread {
        while (!stop) {
            // 执行一些操作
        }
    }

    Thread.sleep(1000)
    stop = true
}
协程

协程是执行异步代码的一种轻量级解决方案。

Kotlin 通过 suspend 关键字和协程构建器来支持协程。

suspend

在函数声明中使用 suspend 关键字标记该函数为挂起函数。

挂起函数可以在一定程度上取代回调函数,简化异步编程。

suspend fun doSomethingAsync() {
    // 执行异步操作,如网络请求或数据库查询
}
协程构建器

协程构建器是启动协程的工具,Kotlin 支持以下几种协程构建器:

  • launch
  • async
  • runBlocking
  • withContext
  • coroutineScope

其中,launchasync 最常用。

launch

launch 创建一个新协程,并立即返回。

import kotlinx.coroutines.*

fun main() {
    GlobalScope.launch {
        doSomethingAsync()
    }
}

async

async 创建一个新协程,并返回一个 Deferred 对象。

Deferred 对象包含一个值(或异常),可以通过 await 方法获取。

import kotlinx.coroutines.*

fun main() = runBlocking {
    val result = GlobalScope.async {
        doSomethingAsync()
    }.await()
    println(result)
}

runBlocking 中启动协程可以等待所有协程执行完毕后退出程序。

withContext

withContext 函数可以在协程中切换线程,并且等待执行完毕后返回结果。

import kotlinx.coroutines.*

suspend fun loadUserData(userId: Int): String = withContext(Dispatchers.IO) {
    // 执行耗时操作,如网络请求或数据库查询
    val result = // ...
    result
}

fun main() = runBlocking {
    val result = loadUserData(1)
    println(result)
}

coroutineScope

coroutineScope 函数可以启动一个新协程作用域,并且等待其中的协程执行完毕后返回结果。

import kotlinx.coroutines.*

suspend fun doSomething(): String {
    delay(1000)
    return "Hello, world!"
}

suspend fun doSomethingElse(): String {
    delay(1000)
    return "Hi there!"
}

suspend fun doBoth(): String = coroutineScope {
    val result1 = async { doSomething() }
    val result2 = async { doSomethingElse() }
    result1.await() + " " + result2.await()
}

fun main() = runBlocking {
    val result = doBoth()
    println(result)
}
结语

Kotlin 提供了方便的线程编程 API 和支持协程的语言特性,使得异步编程更加简单和优雅。