[BAEL-19885] - Move articles out of core-kotlin part4
This commit is contained in:
7
core-kotlin-modules/core-kotlin-concurrency/README.md
Normal file
7
core-kotlin-modules/core-kotlin-concurrency/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## Core Kotlin Concurrency
|
||||
|
||||
This module contains articles about concurrency in Kotlin.
|
||||
|
||||
### Relevant articles:
|
||||
- [Threads vs Coroutines in Kotlin](https://www.baeldung.com/kotlin-threads-coroutines)
|
||||
- [Introduction to Kotlin Coroutines](https://www.baeldung.com/kotlin-coroutines)
|
||||
41
core-kotlin-modules/core-kotlin-concurrency/pom.xml
Normal file
41
core-kotlin-modules/core-kotlin-concurrency/pom.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>core-kotlin-concurrency</artifactId>
|
||||
<name>core-kotlin-concurrency</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.core-kotlin-modules</groupId>
|
||||
<artifactId>core-kotlin-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<kotlin.version>1.3.30</kotlin.version>
|
||||
<assertj.version>3.10.0</assertj.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.threadsvscoroutines
|
||||
|
||||
class SimpleRunnable: Runnable {
|
||||
|
||||
override fun run() {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.threadsvscoroutines
|
||||
|
||||
class SimpleThread: Thread() {
|
||||
|
||||
override fun run() {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package com.baeldung.coroutines
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import org.junit.Test
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.system.measureTimeMillis
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
||||
class CoroutinesTest {
|
||||
|
||||
@Test
|
||||
fun givenBuildSequence_whenTakeNElements_thenShouldReturnItInALazyWay() {
|
||||
//given
|
||||
val fibonacciSeq = sequence {
|
||||
var a = 0
|
||||
var b = 1
|
||||
|
||||
yield(1)
|
||||
|
||||
while (true) {
|
||||
yield(a + b)
|
||||
|
||||
val tmp = a + b
|
||||
a = b
|
||||
b = tmp
|
||||
}
|
||||
}
|
||||
|
||||
//when
|
||||
val res = fibonacciSeq.take(5).toList()
|
||||
|
||||
//then
|
||||
assertEquals(res, listOf(1, 1, 2, 3, 5))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenLazySeq_whenTakeNElements_thenShouldReturnAllElements() {
|
||||
//given
|
||||
val lazySeq = sequence {
|
||||
print("START ")
|
||||
for (i in 1..5) {
|
||||
yield(i)
|
||||
print("STEP ")
|
||||
}
|
||||
print("END")
|
||||
}
|
||||
//when
|
||||
val res = lazySeq.take(10).toList()
|
||||
|
||||
//then
|
||||
assertEquals(res, listOf(1, 2, 3, 4, 5))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAsyncCoroutine_whenStartIt_thenShouldExecuteItInTheAsyncWay() {
|
||||
//given
|
||||
val res = mutableListOf<String>()
|
||||
|
||||
//when
|
||||
runBlocking {
|
||||
val promise = launch(Dispatchers.Default) { expensiveComputation(res) }
|
||||
res.add("Hello,")
|
||||
promise.join()
|
||||
}
|
||||
|
||||
//then
|
||||
assertEquals(res, listOf("Hello,", "word!"))
|
||||
}
|
||||
|
||||
|
||||
suspend fun expensiveComputation(res: MutableList<String>) {
|
||||
delay(1000L)
|
||||
res.add("word!")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenHugeAmountOfCoroutines_whenStartIt_thenShouldExecuteItWithoutOutOfMemory() {
|
||||
runBlocking<Unit> {
|
||||
//given
|
||||
val counter = AtomicInteger(0)
|
||||
val numberOfCoroutines = 100_000
|
||||
|
||||
//when
|
||||
val jobs = List(numberOfCoroutines) {
|
||||
launch(Dispatchers.Default) {
|
||||
delay(1L)
|
||||
counter.incrementAndGet()
|
||||
}
|
||||
}
|
||||
jobs.forEach { it.join() }
|
||||
|
||||
//then
|
||||
assertEquals(counter.get(), numberOfCoroutines)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenCancellableJob_whenRequestForCancel_thenShouldQuit() {
|
||||
runBlocking<Unit> {
|
||||
//given
|
||||
val job = launch(Dispatchers.Default) {
|
||||
while (isActive) {
|
||||
//println("is working")
|
||||
}
|
||||
}
|
||||
|
||||
delay(1300L)
|
||||
|
||||
//when
|
||||
job.cancel()
|
||||
|
||||
//then cancel successfully
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = CancellationException::class)
|
||||
fun givenAsyncAction_whenDeclareTimeout_thenShouldFinishWhenTimedOut() {
|
||||
runBlocking<Unit> {
|
||||
withTimeout(1300L) {
|
||||
repeat(1000) { i ->
|
||||
println("Some expensive computation $i ...")
|
||||
delay(500L)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenHaveTwoExpensiveAction_whenExecuteThemAsync_thenTheyShouldRunConcurrently() {
|
||||
runBlocking<Unit> {
|
||||
val delay = 1000L
|
||||
val time = measureTimeMillis {
|
||||
//given
|
||||
val one = async(Dispatchers.Default) { someExpensiveComputation(delay) }
|
||||
val two = async(Dispatchers.Default) { someExpensiveComputation(delay) }
|
||||
|
||||
//when
|
||||
runBlocking {
|
||||
one.await()
|
||||
two.await()
|
||||
}
|
||||
}
|
||||
|
||||
//then
|
||||
assertTrue(time < delay * 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenTwoExpensiveAction_whenExecuteThemLazy_thenTheyShouldNotConcurrently() {
|
||||
runBlocking<Unit> {
|
||||
val delay = 1000L
|
||||
val time = measureTimeMillis {
|
||||
//given
|
||||
val one = async(Dispatchers.Default, CoroutineStart.LAZY) { someExpensiveComputation(delay) }
|
||||
val two = async(Dispatchers.Default, CoroutineStart.LAZY) { someExpensiveComputation(delay) }
|
||||
|
||||
//when
|
||||
runBlocking {
|
||||
one.await()
|
||||
two.await()
|
||||
}
|
||||
}
|
||||
|
||||
//then
|
||||
assertTrue(time > delay * 2)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun someExpensiveComputation(delayInMilliseconds: Long) {
|
||||
delay(delayInMilliseconds)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.baeldung.threadsvscoroutines
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class CoroutineUnitTest {
|
||||
|
||||
@Test
|
||||
fun whenCreateCoroutineWithLaunchWithoutContext_thenRun() = runBlocking {
|
||||
|
||||
val job = launch {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateCoroutineWithLaunchWithDefaultContext_thenRun() = runBlocking {
|
||||
|
||||
val job = launch(Dispatchers.Default) {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateCoroutineWithLaunchWithUnconfinedContext_thenRun() = runBlocking {
|
||||
|
||||
val job = launch(Dispatchers.Unconfined) {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateCoroutineWithLaunchWithDedicatedThread_thenRun() = runBlocking {
|
||||
|
||||
val job = launch(newSingleThreadContext("dedicatedThread")) {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateAsyncCoroutine_thenRun() = runBlocking {
|
||||
|
||||
val deferred = async(Dispatchers.IO) {
|
||||
return@async "${Thread.currentThread()} has run."
|
||||
}
|
||||
|
||||
val result = deferred.await()
|
||||
println(result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.threadsvscoroutines
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class ThreadUnitTest {
|
||||
|
||||
@Test
|
||||
fun whenCreateThread_thenRun() {
|
||||
|
||||
val thread = SimpleThread()
|
||||
thread.start()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateThreadWithRunnable_thenRun() {
|
||||
|
||||
val threadWithRunnable = Thread(SimpleRunnable())
|
||||
threadWithRunnable.start()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateThreadWithSAMConversions_thenRun() {
|
||||
|
||||
val thread = Thread {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
thread.start()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateThreadWithMethodExtension_thenRun() {
|
||||
|
||||
thread(start = true) {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user