11package cub.concurrent.answers
22
3- import kotlin.concurrent.*
4- import java.util.concurrent.locks.*
5-
6- /*
7- * Implement simple thread-safe blocking stack.
8- * Use usual mutable list as an underlying storage.
9- *
10- * Methods can block the calling thread if they are executed concurrently with other methods.
11- * Additionally, pop operation can also block the thread if the stack is empty ---
12- * in this case it should wait until some value will be pushed to the stack.
13- */
14- class SynchronizedBlockingStack <T > {
15- private val list = mutableListOf<T >()
16- private val lock = ReentrantLock ()
17- private val condition = lock.newCondition()
18-
19- fun push (value : T ) = lock.withLock {
20- list.add(value)
21- condition.signal()
22- }
23-
24- fun pop (): T = lock.withLock {
25- while (list.isEmpty()) {
26- condition.await()
3+ import java.util.concurrent.ConcurrentLinkedQueue
4+ import kotlin.concurrent.thread
5+
6+ fun <T > Collection<T>.parallelForEach (nThreads : Int , block : (T ) -> Unit ) {
7+ require(nThreads > 0 ) { " The number of threads must be > 0" }
8+ val queue = ConcurrentLinkedQueue (this )
9+ val threadPool = (0 until nThreads).map { _ ->
10+ thread {
11+ while (true ) {
12+ block(queue.poll() ? : return @thread)
13+ }
2714 }
28- list.removeLast()
29- }
30-
31- fun top (): T ? = lock.withLock {
32- list.lastOrNull()
33- }
34-
35- fun size (): Int = lock.withLock {
36- list.size
37- }
38- }
39-
40- fun test1 () {
41- val stack = SynchronizedBlockingStack <Int >()
42- thread {
43- stack.push(1 )
44- }
45- thread {
46- stack.push(2 )
47- stack.push(3 )
48- }
49- thread {
50- val a = stack.pop()
51- val b = stack.pop()
52- val c = stack.pop()
53- println (" a=$a , b=$b , c=$c " )
54- // can print either:
55- // a=3, b=2, a=1
56- // a=1, b=3, c=2
57- // a=3, b=1, a=2
5815 }
59- }
60-
61- fun test2 () {
62- val stack = SynchronizedBlockingStack <Int >()
63- thread {
64- println (" push(1)" )
65- stack.push(1 )
66- }
67- thread {
68- val r = stack.pop()
69- println (" pop(): $r " )
70- }
71- // can only print lines in the following sequence:
72- // push(1), pop():1
16+ threadPool.forEach { it.join() }
7317}
7418
7519fun main () {
76- test1()
77- test2()
20+ (1 .. 10 ).toList().parallelForEach(4 ) { i ->
21+ println (" ${i * i} " )
22+ }
7823}
0 commit comments