[BAEL-19885] - Move articles out of core-kotlin part4

This commit is contained in:
catalin-burcea
2019-12-27 13:36:41 +02:00
parent b38e420b11
commit 5e9a17c306
44 changed files with 194 additions and 57 deletions

View 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)

View 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>

View File

@@ -0,0 +1,8 @@
package com.baeldung.threadsvscoroutines
class SimpleRunnable: Runnable {
override fun run() {
println("${Thread.currentThread()} has run.")
}
}

View File

@@ -0,0 +1,8 @@
package com.baeldung.threadsvscoroutines
class SimpleThread: Thread() {
override fun run() {
println("${Thread.currentThread()} has run.")
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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.")
}
}
}