Skip to content

Commit 093f35c

Browse files
committed
WIP
1 parent 202314b commit 093f35c

23 files changed

+1073
-59
lines changed

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,23 @@
2222

2323
### Metrics
2424
```text
25-
15001 number of properties
26-
10391 number of functions
27-
8857 number of classes
28-
230 number of packages
29-
3488 number of kt files
25+
15007 number of properties
26+
10398 number of functions
27+
8859 number of classes
28+
231 number of packages
29+
3489 number of kt files
3030
```
3131

3232

3333
### Complexity Report
3434
```text
35-
259554 lines of code (loc)
36-
158990 source lines of code (sloc)
37-
116006 logical lines of code (lloc)
38-
72493 comment lines of code (cloc)
39-
24708 cyclomatic complexity (mcc)
40-
20232 cognitive complexity
35+
259717 lines of code (loc)
36+
159153 source lines of code (sloc)
37+
116114 logical lines of code (lloc)
38+
72470 comment lines of code (cloc)
39+
24752 cyclomatic complexity (mcc)
40+
20233 cognitive complexity
4141
0 number of total code smells
4242
45 comment source ratio
43-
212 mcc per 1,000 lloc
43+
213 mcc per 1,000 lloc
4444
```

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ kapt = "2.1.0" # https://kotlinlang.org/docs/kapt.html
1212
slf4j = "2.0.17" # https://www.slf4j.org TODO remove
1313
rxjava = "3.1.10" # https://github.com/ReactiveX/RxJava
1414
rxkotlin = "3.0.1" # https://github.com/ReactiveX/RxKotlin
15-
lincheck = "2.36" # https://github.com/JetBrains/lincheck
15+
lincheck = "2.29" # https://github.com/JetBrains/lincheck
1616
serialization = "1.8.1" # https://github.com/Kotlin/kotlinx.serialization
1717
retrofit = "2.11.0" # https://github.com/square/retrofit
1818
okhttp = "5.0.0-alpha.14" # https://square.github.io/okhttp/changelogs/changelog
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Merge Sorted Array

src/main/kotlin/dev/shtanko/concurrency/AtomicReferenceArrayExample.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,19 @@ import java.util.concurrent.atomic.AtomicReferenceArray
2424
object AtomicReferenceArrayExample {
2525
@JvmStatic
2626
fun main(args: Array<String>) {
27-
// Initialize an AtomicReferenceArray with 5 elements
2827
val atomicArray = AtomicReferenceArray<String>(5)
2928

30-
// Set values in the array
3129
atomicArray.set(0, "A")
3230
atomicArray.set(1, "B")
3331
atomicArray.set(2, "C")
3432
atomicArray.set(3, "D")
3533
atomicArray.set(4, "E")
3634

37-
// Get and print values from the array
3835
println("Initial values:")
3936
for (i in 0 until atomicArray.length()) {
4037
println("Index $i: ${atomicArray.get(i)}")
4138
}
4239

43-
// Update a value using compareAndSet
4440
val indexToUpdate = 2
4541
val oldValue = "C"
4642
val newValue = "Z"
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
## 🧠 `ArrayBlockingQueue`
2+
3+
`ArrayBlockingQueue` is a bounded, **blocking queue** implementation in Java that uses an array to store the elements.
4+
It is a **thread-safe** queue designed for situations where a fixed-size queue is needed, and elements are added or removed in a **first-in-first-out (FIFO)** order.
5+
6+
---
7+
8+
### 🔍 Key Features
9+
10+
- **Thread-safe**: Provides safe concurrent access for multiple threads.
11+
- **Blocking behavior**: It **blocks** threads when the queue is full or empty (for `put()` and `take()` operations).
12+
- **Bounded capacity**: The queue has a fixed capacity, preventing unbounded growth.
13+
- **FIFO order**: Elements are dequeued in a first-in-first-out order.
14+
15+
---
16+
17+
### ✅ When to Use
18+
19+
- ✅ You need a **bounded queue** with a **fixed capacity**.
20+
- ✅ Threads should block when the queue is full or empty (e.g., producer-consumer pattern).
21+
- ✅ You want to ensure that the queue doesn’t grow indefinitely, thereby controlling memory usage.
22+
23+
---
24+
25+
### ❌ When Not to Use
26+
27+
- ❌ If you need a **non-blocking** queue or one that grows dynamically (consider `ConcurrentLinkedQueue` or `LinkedBlockingQueue`).
28+
- ❌ When you need **unbounded queue capacity** or if memory control isn’t a priority.
29+
30+
---
31+
32+
### 📌 Kotlin Example
33+
34+
```kotlin
35+
import java.util.concurrent.ArrayBlockingQueue
36+
37+
fun main() {
38+
// Creating a bounded queue with a capacity of 3
39+
val queue = ArrayBlockingQueue<String>(3)
40+
41+
// Producer thread: Adds elements to the queue
42+
val producer = Thread {
43+
try {
44+
queue.put("Task 1") // Will block if the queue is full
45+
queue.put("Task 2")
46+
queue.put("Task 3")
47+
println("Producer finished adding tasks.")
48+
} catch (e: InterruptedException) {
49+
e.printStackTrace()
50+
}
51+
}
52+
53+
// Consumer thread: Removes elements from the queue
54+
val consumer = Thread {
55+
try {
56+
println("Consumer started")
57+
println("Taken: ${queue.take()}") // Will block if the queue is empty
58+
println("Taken: ${queue.take()}")
59+
println("Taken: ${queue.take()}")
60+
println("Consumer finished processing tasks.")
61+
} catch (e: InterruptedException) {
62+
e.printStackTrace()
63+
}
64+
}
65+
66+
// Start producer and consumer threads
67+
producer.start()
68+
consumer.start()
69+
70+
// Wait for threads to finish
71+
producer.join()
72+
consumer.join()
73+
}
74+
```
75+
76+
---
77+
78+
### 💡 Summary Table
79+
80+
| Feature | `ArrayBlockingQueue` |
81+
|-----------------------|-----------------------------|
82+
| Thread-safe | ✅ Yes |
83+
| Blocking operations | ✅ Yes (blocks on full/empty) |
84+
| Capacity | ✅ Bounded (fixed size) |
85+
| FIFO order | ✅ Yes |
86+
| Best use case | ✅ Producer-consumer pattern, controlling memory usage |
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
## 🧠 `ConcurrentHashMap` in Java and Kotlin
2+
3+
`ConcurrentHashMap` is a thread-safe and highly performant implementation of `Map` designed for concurrent access without needing to synchronize the entire map.
4+
5+
---
6+
7+
### 🔍 Key Features
8+
9+
- Allows **concurrent reads and writes** by segmenting the map internally.
10+
- **Does not allow `null` keys or values**.
11+
- **No need to synchronize** explicitly for most operations.
12+
- Iterators are **weakly consistent** — they reflect some (not necessarily all) changes made during iteration and do **not** throw `ConcurrentModificationException`.
13+
14+
---
15+
16+
### ✅ When to Use
17+
18+
- ✅ You need a **high-performance thread-safe map**.
19+
- ✅ Multiple threads **frequently read and write** concurrently.
20+
- ✅ You're building multi-threaded services, caches, or registries.
21+
22+
---
23+
24+
### ❌ When Not to Use
25+
26+
- ❌ You need to store `null` values (not allowed).
27+
- ❌ In single-threaded scenarios — prefer regular `HashMap`.
28+
29+
---
30+
31+
### 📌 Kotlin Example
32+
33+
```kotlin
34+
import java.util.concurrent.ConcurrentHashMap
35+
36+
fun main() {
37+
val map = ConcurrentHashMap<String, String>()
38+
39+
map["name"] = "Alice"
40+
map["city"] = "Wonderland"
41+
42+
// Accessing elements
43+
println("Name: ${map["name"]}")
44+
println("City: ${map["city"]}")
45+
46+
// Iterating over keys
47+
for (key in map.keys) {
48+
println("$key => ${map[key]}")
49+
}
50+
51+
// Safe concurrent access (example using multiple threads)
52+
val threads = List(10) { i ->
53+
Thread {
54+
map["thread-$i"] = "value-$i"
55+
}
56+
}
57+
58+
threads.forEach { it.start() }
59+
threads.forEach { it.join() }
60+
61+
println("Map size after concurrency: ${map.size}")
62+
}
63+
```
64+
65+
---
66+
67+
### 💡 Summary Table
68+
69+
| Feature | `ConcurrentHashMap` |
70+
|----------------------|-----------------------------|
71+
| Thread-safe | ✅ Yes |
72+
| Null keys/values | ❌ Not allowed |
73+
| Performance | ✅ High under concurrency |
74+
| Iterators | ✅ Weakly consistent |
75+
| Best use case | ✅ Multi-threaded apps |
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
## 🧠 `ConcurrentLinkedDeque`
2+
3+
`ConcurrentLinkedDeque` is a thread-safe, non-blocking **double-ended queue** (deque) that allows elements to be added or removed from both ends of the queue concurrently.
4+
It provides a **lock-free** implementation for high-performance operations in concurrent environments.
5+
6+
---
7+
8+
### 🔍 Key Features
9+
10+
- **Thread-safe**: Allows multiple threads to access and modify the deque concurrently without requiring synchronization.
11+
- **Non-blocking**: Provides lock-free, non-blocking operations for adding and removing elements from both ends of the deque.
12+
- **FIFO Order**: Elements are dequeued in a **first-in-first-out** order, but since it’s a deque, elements can also be added and removed from both ends.
13+
- **Unbounded**: It grows as needed (limited only by available memory).
14+
15+
---
16+
17+
### ✅ When to Use
18+
19+
- ✅ You need a **high-performance thread-safe deque** that allows **adding/removing elements** from both ends.
20+
- ✅ You require **non-blocking behavior** for both ends of the deque in a **multi-threaded environment**.
21+
- ✅ You have scenarios like **task scheduling**, **buffering**, or **job queues** that require fast access from both ends.
22+
23+
---
24+
25+
### ❌ When Not to Use
26+
27+
- ❌ If you need to block threads while waiting for elements (consider using `BlockingDeque` in that case).
28+
- ❌ If you only need a simple queue or stack, consider using `ConcurrentLinkedQueue` or `Stack` instead.
29+
30+
---
31+
32+
### 📌 Kotlin Example
33+
34+
```kotlin
35+
import java.util.concurrent.ConcurrentLinkedDeque
36+
37+
fun main() {
38+
val deque = ConcurrentLinkedDeque<String>()
39+
40+
// Adding elements to both ends of the deque
41+
deque.offerFirst("Task 1") // Adds at the front
42+
deque.offerLast("Task 2") // Adds at the back
43+
deque.offerFirst("Task 3") // Adds at the front
44+
deque.offerLast("Task 4") // Adds at the back
45+
46+
// Polling elements from both ends
47+
println("Polled from front: ${deque.pollFirst()}") // Output: Task 3
48+
println("Polled from back: ${deque.pollLast()}") // Output: Task 4
49+
50+
// Peek at the front and back without removing
51+
println("Peek front: ${deque.peekFirst()}") // Output: Task 1
52+
println("Peek back: ${deque.peekLast()}") // Output: Task 2
53+
54+
// Checking if the deque is empty
55+
println("Is deque empty? ${deque.isEmpty()}") // Output: false
56+
57+
// Safe concurrent access example
58+
val threads = List(5) { i ->
59+
Thread {
60+
deque.offerLast("Task from thread $i")
61+
}
62+
}
63+
64+
threads.forEach { it.start() }
65+
threads.forEach { it.join() }
66+
67+
// Polling all tasks after concurrent additions
68+
while (deque.isNotEmpty()) {
69+
println("Polled: ${deque.pollFirst()}")
70+
}
71+
}
72+
```
73+
74+
---
75+
76+
### 💡 Summary Table
77+
78+
| Feature | `ConcurrentLinkedDeque` |
79+
|-----------------------|-----------------------------|
80+
| Thread-safe | ✅ Yes |
81+
| Non-blocking | ✅ Yes (lock-free) |
82+
| FIFO order | ✅ Yes |
83+
| Allows adding/removing from both ends | ✅ Yes |
84+
| Capacity | ❌ Unbounded (limited by memory) |
85+
| Best use case | ✅ Task scheduling, job queues, buffers |

0 commit comments

Comments
 (0)