本文已参加好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你应战!

面试的时分经常会被问及多线程同步的问题,例如:

“ 现有 Task1、Task2 等多个并行使命kotlin教程,怎样等安全生产月待悉数实施结束后,实施 Task3。”

在 Kotlin 中咱们有多种结束方法,本文将悉数这些办面试常见问题及答复技巧法做了拾掇,主张保藏面试必问10大问题答复

1. Thread.join
2. Synchroniz多线程的完成方法ed
3. Reentrant前端Lock
4. BlockingQue安全教育ue
5. CountDown安全教育渠道Latch
6. CyclicBarrier
7. CAS
8. Future
9. Com前端和后端的差异pletableFuture
10. Rxja多线程的并发问题va
11. Coroutine
12. Flow

咱们先定义三个Task,模仿上述场景, Task3 根据 Task1、Task2 回来的作用拼接字符多线程的完成方法串,每个 Task 经过 sleep 模仿耗时:
面试必备:Kotlin 线程同步的 N 种方法

val task1: () -> String = {
sleep(2000)
"Hello".also { prin多线程使用场景比如tln("task1 finished: $多线程编程it") }
}
val task2: () -> String = {
sleep(2000)
"World".also { println("task2 finished: $it") }
}
val task3: (String, String) -> String = { p1, p2 ->
sleep(2000)
"$p1 $p2".also { println("task3 finikotlin核心编程shed: $it") }
}

1. Thread.join()

Kotlin 兼容 Java,Java 的悉数线程东西默许都能够运用。其中最简略的线程同步方法就是运用 Thread前端join()

@Test
fun test_join() {
lateinit var s1: String
lateinit var s2: String
val t1 = Thread { s1 = t面试毛遂自荐一分钟ask1() }
val t2 = Thread { s2 =多线程使用场景比如 task2() }kotlin和java
t1.start()
t2.start前端学什么()
t1.join()
t2.join()
task3(s1, s2)
}

2. S前端ynchrkotlin面试题onkotlin下载ized

前端开发是干什么的synchronized 锁进行同步

	@Test
fun test_synchrnoized() {
lateinit var s1: String
late面试毛遂自荐3分钟通用ini安全教育t var s2: String
Thread {kotlin下载
skotlin下载ynchronized(Unit) {
s1 = task1()
}
}.start()
s2 = task2()
synchronized(Unit) {
task3(s1, s2)
}
}

可是假定超越三个使命,运前端结构s多线程并发ynchrnoized 这种写法就比较别扭了,为了同步多个并行使命的作用需求声明n个锁,并嵌套n个 synchronized

3. ReentrantLock

ReentrantLock 是 JUC 供给的线程锁,能够替换 synchronized 的运用

	@Test
fun test_ReentrantLock(前端面试题) {
lateini面试毛遂自荐简单大方t var s1: String
lateinit var s2: String
val lock = ReentrantLock()
Thread {
lock.lo安全ck()
s1 = task1()
lock多线程使用场景比如.unlock()
}.面试问题大全及答案大全start()
s2面试毛遂自荐简单大方 = task2()
lock.lockkotlin为什么流行不起来()
task3(s1, s2)
lock.unlock()
}多线程和多进程的差异

ReentrantLock 的利益是,当有多个并行使命时是不安全工程会呈面试技巧和注意事项现嵌套 synchrnoized 的问题,但仍然需求创立多个 lock 办理不同的使命,

4. Bloc安全工程kingQueue

堵塞队伍内部也是经过 Lock 结束的,所以也能够抵达同步锁的作用

	@Test
fun test_blockingQue前端面试题ue() {
lateinit var s1: String
lateinit var s2: String
v前端面试题al queue = SynchronousQueue<Unit>()
Thread {
s1 = task1()
queue.put(Unit)
}.start()
s2 = task2()
queue.take()
task3(s1, s2)
}

当然,堵塞队伍更多是运用在生产/消费场景中的同步。

5. C多线程是什么意思ountDownLatch

JUC 中的锁大都根据 AQS 结束的,能够分为独享锁和同享锁。ReentrantLock 就是一种独享锁。相比之下,同享锁更适合本场景。 例如 CountDownLatch,它能够让一个安全生产法线程一向处于堵塞状态,直到kotlin面试题其他线程的实施悉数结束:

	@Te多线程的并发问题st
fkotlin实战un tes安全工程t_countdownlatch() {
lateinit var s1: String
lateinit var s2: String
v面试技巧al cd = CountDownLatch(2)
Thread() {
s1 = task1()
cd.countDown()
}.start()
Thread() {
s2 =前端工程师 task2()
cd.countDown()
}.star多线程cpu有什么好处t()
cd.await()
task3(s1, s2)
}

同享锁的利益是不必为了每个使命都创立独自的锁,即使再多并行使命写起来也很轻松

6. CyclicBarrier

CyclKotlinicBarrie多线程面试题r 是 JUC 供给的另一种同享锁机制,它能够让一组线程安全生产法抵达一个同步点后再一起继续安全运转,其中恣意一个线程未抵达同安全期是哪几天步点,其他已抵达的线程均会被堵塞。

CountDownLatch 的差前端结构异在于 CountDownLatch 是一次性的,而 CyclicBarrierkotlin怎样读以被重置后重复运用,这也正是 Cycli安全期是哪几天c 的命名由来,能够循环运用

	@Test
fun test_CyclicBarrier() {
lat多线程并发einit var s1: String
l面试毛遂自荐一分钟ateinit var s2: String
v安全教育渠道登录进口al cb = CyclicBarrier(3)
Thread {
s1 = task1()
cb.await()
}.start()
Thread() {
s2 =安全期是哪几天 task1()
cb.await()
}.start()
cb.await(前端工程师)
task3(s1, s2)
}

7. CAS

AQS 内部经过自旋锁结束同步Kotlin,自旋锁的实质是利用 CompareAndSwap 避免线程堵塞的开支。
因而,咱们能够运用根据 CASkotlin教程 的原子类计数多线程和多进程的差异,抵达结束无锁操作的目的。

 	@Test
f安全期计算器un test_cas() {
lateinit var s1: String
lateinit var s2: String
val cas = AtomicInteger(2)安全工程
Thread {
s1 = task1()
c面试技巧as.getAndDecrement()
}.start()
Thread {
s2前端技术 = task2()
cas.getAndDecrement()
}.start()
while (安全教育渠道登录cas.get() != 0) {}
task3(s1, s2)
}

while 循环空转看起来有些浪费资源,可是自旋锁的实质就是这样,所以 CAS 仅仅适用于一些cpu密集型的短使命同步。

volkotlin面试题atile

看到安全教育渠道登录进口 CAS 的无锁结束,或许许多人会安全期是哪几天想到 volatile, 是否也能结束无锁的线程安全?

 	@Test
fun test_Volatile() {
lateinit var s1: Stri面试必问10大问题答复ng
lateinit var skotlin教程2: String
Thread {
s1 = task1()
cnt--
}.start()
Thread {
s2 = task2(多线程使用场景比如)
cnt-前端-
}.start()
whi前端和后端的差异le (cnt != 0) {
}
task3(s1, s2)
}

留心,这种写法是过失的
volatile 能保证可见性,可是不能保证原面试必问10大问题答复子性,cnt-- 并非线程安全,需求加锁操作

8. Future

上面不安全期计算器管有锁操作还是无锁操作,都需求定义两个变量s1s2记录作用十分不方便面试必问10大问题答复利。
Java 1.5 开端,供给了 CallableFuture ,能够在使命面试毛遂自荐一分钟实施结束时回来作用。

@Test
fun tes多线程编程t_futurekotlin官网() {
val future1多线程的完成方法 = FutureTask(Callable(task1))
val fukotlin面试题ture2 = FutureTask(Callable(安全工程task2安全教育渠道登录))
Executors.newCachedThreadPool().execute(future1)面试毛遂自荐一分钟
Executors.newCa安全期计算器chedThreadPool().execute(future2)
takotlin面试题sk3(future1.get(), future2.get())
}

经过 future.get(),能够同步等候作用回来,写起来十分便当

9. CompletableFuture

future.get() 虽然便当,可是会堵塞线程。 Java 8 中引入了 Com前端开发pletableFuture ,他结束了 Future 接口的一起完安全期计算器结了 CompletionStage 接口。 CompletableFuture 能够针对多个 CompletionS前端开发需要学什么tage 进行逻辑组合、结束凌乱的异步编程。 这些逻辑组合的方法以回调的形前端和后端的差异式避免了线程堵塞:

@Test
fun test_CompletableF前端面试题uture() {
CompletableFuture.supplyAkotlin下载sync(ta多线程cpu有什么好处sk1)
.thenCombine(CompletableFuture.supplyAsync(task2)) { p1, p2 ->
t安全生产月ask3(p1, p2)
}.join()
}

10. RxJava

R面试xJava 供给的各种操作符以及线程切换才能相同能够帮忙咱们结束需求:
zip 操作符能够组合两个 Obs多线程使用场景比如ervable 的效kotlin怎样读果;subscribeOn 用来发动异步使命

@Test
fun test_Rxjava() {
Ob多线程下载servable.zip(kotlin言语
Observablekotlin实战.fromCallable(Callable(task1))
.subscribeOn(Schedulers.newThread()),
Observable.fromCallable(Callable(task2))
.sub多线程面试题scribeOn(Schedulers.newThread()),
BiFunction(task3)
).test().awaitTerminalEvent()
}

11. Coroutine

前面讲了那么多,其实都是 Java 的东西。 Coroutine 总算算得上是 Kotlin 特有的东西了:

@Test
fun test_coroutine() {
runBlocking {
val c1 = asyn面试必问10大问题答复c(Dispatchers.IO) {
task1()
}
val c2安全期是哪几天 = async(Dispatchers.IO) {
task2()
}
task3(c1.awakotlin面试题it(), c2.await())
}
}

写起来特别酣畅多线程cpu有什么好处,能够说是集前面各类东西的利益于一身。

12. Flo前端和后端哪个薪酬高w

Flow多线程下载 就是 CoKotlinroutine 版的 RxJava,具有许多 RxJava 的操作符,例如 zip:


@Test
fun test_flow() {
val flow1 = flow<String>安全教育渠道登录进口 { emit(task1()) }
val flow2 = flow&lt多线程是什么意思;StringKotlin> { emit(task2()) }
runBlocking {
flow1.zip(flow2) { t1, t2 ->
task3(t1, t2)
}.flowOn(Dispatchers.IO)
.collect()
}
}

flowOn 使得 Task 在异步核算前端开发并发射作用。

总结

上面这么多方法,就像茴香豆的“茴”字的四种写法,没必要都把握。作为定论,在 Kotlin 上最好用的线程同步方案首面试必问10大问题答复推协程!