169 lines
5.1 KiB
Kotlin
169 lines
5.1 KiB
Kotlin
/*
|
|
* This Kotlin source file was generated by the Gradle 'init' task.
|
|
*/
|
|
package threadsafe
|
|
|
|
import io.kotest.core.spec.style.StringSpec
|
|
import kotlinx.coroutines.asCoroutineDispatcher
|
|
import kotlinx.coroutines.coroutineScope
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.launch
|
|
import kotlinx.coroutines.withContext
|
|
import org.junit.jupiter.api.assertThrows
|
|
import java.util.Collections
|
|
import java.util.Hashtable
|
|
import java.util.concurrent.ConcurrentHashMap
|
|
import java.util.concurrent.CopyOnWriteArrayList
|
|
import java.util.concurrent.CountDownLatch
|
|
import java.util.concurrent.Executors
|
|
import kotlin.math.max
|
|
import kotlin.random.Random
|
|
|
|
val dispatcher = Executors.newCachedThreadPool().asCoroutineDispatcher()
|
|
|
|
class LibraryTest : StringSpec({
|
|
"CountDownLatch" {
|
|
withContext(dispatcher) {
|
|
val createdValues = mutableListOf<Int>()
|
|
val countDownLatch = CountDownLatch(3)
|
|
|
|
(1..5).forEach { index ->
|
|
launch {
|
|
delay(Random.nextLong(0, 100))
|
|
createdValues.add(index)
|
|
println("Added value $index")
|
|
countDownLatch.countDown()
|
|
}
|
|
}
|
|
|
|
(1..3).forEach { _ ->
|
|
launch {
|
|
countDownLatch.await()
|
|
println("The sum is ${createdValues.sum()}")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
"Non-blocking CountDownLatch" {
|
|
withContext(dispatcher) {
|
|
val createdValues = mutableListOf<Int>()
|
|
val countDownLatch = CountDownLatch(3)
|
|
|
|
(1..5).forEach { index ->
|
|
launch {
|
|
delay(Random.nextLong(0, 100))
|
|
createdValues.add(index)
|
|
println("Added value $index")
|
|
countDownLatch.countDown()
|
|
}
|
|
}
|
|
|
|
while (countDownLatch.count > 0) {
|
|
delay(10)
|
|
}
|
|
println("The sum is ${createdValues.sum()}")
|
|
}
|
|
}
|
|
|
|
"SynchronizedList" {
|
|
withContext(dispatcher) {
|
|
val unsyncList = mutableListOf<Int>()
|
|
coroutineScope {
|
|
(1..10000).forEach { index ->
|
|
launch {
|
|
unsyncList.add(index)
|
|
}
|
|
}
|
|
}
|
|
println("Unsync list size: ${unsyncList.size}")
|
|
|
|
val syncList = Collections.synchronizedList(mutableListOf<Int>())
|
|
coroutineScope {
|
|
(1..10000).forEach { index ->
|
|
launch {
|
|
syncList.add(index)
|
|
}
|
|
}
|
|
}
|
|
println("Sync list size: ${syncList.size}")
|
|
}
|
|
}
|
|
|
|
"CopyOnWriteArrayList" {
|
|
withContext(dispatcher) {
|
|
val ordinaryList = Collections.synchronizedList((1..10000).toMutableList())
|
|
launch {
|
|
delay(5)
|
|
var maximum = 0
|
|
assertThrows<ConcurrentModificationException> {
|
|
for (number in ordinaryList) {
|
|
maximum = max(number, maximum)
|
|
}
|
|
println("The maximum is: $maximum")
|
|
}
|
|
}
|
|
(20000..25000).forEach {
|
|
launch {
|
|
ordinaryList.add(it)
|
|
}
|
|
}
|
|
|
|
val copyOnWriteList = CopyOnWriteArrayList((1..10000).toMutableList())
|
|
launch {
|
|
delay(5)
|
|
var maximum = 0
|
|
for (number in copyOnWriteList) {
|
|
if (number == 1) {
|
|
println("Starting to compare")
|
|
}
|
|
maximum = max(number, maximum)
|
|
}
|
|
println("The maximum is: $maximum")
|
|
}
|
|
(20000..25000).forEach { number ->
|
|
launch {
|
|
println("Adding $number")
|
|
copyOnWriteList.add(number)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
"HashTable" {
|
|
withContext(dispatcher) {
|
|
val hashTable = Hashtable<String, Int>()
|
|
(1..10).forEach { number ->
|
|
launch {
|
|
println("Inserting key=$number")
|
|
hashTable["key"] = number
|
|
println("Inserted key=$number")
|
|
}
|
|
launch {
|
|
println("Inserting other=$number")
|
|
hashTable["other"] = number
|
|
println("Inserted other=$number")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
"ConcurrentHashMap" {
|
|
withContext(dispatcher) {
|
|
val hashMap = ConcurrentHashMap<String, Int>()
|
|
(1..10).forEach { number ->
|
|
launch {
|
|
println("Inserting key=$number")
|
|
hashMap["key"] = number
|
|
println("Inserted key=$number")
|
|
}
|
|
launch {
|
|
println("Inserting other=$number")
|
|
hashMap["other"] = number
|
|
println("Inserted other=$number")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|