使用kotlin的coroutine机制,可以很容易实现一个generator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import java.util.concurrent.atomic.AtomicReference
import kotlin.coroutines.experimental.*


class Generater<T : Any> private constructor() {
private var mContinuation: AtomicReference<Continuation<Unit>?> = AtomicReference(null)
private val values: ThreadLocal<T?> = ThreadLocal()
/**
* -1:结束
* 0:未开始
* 1:开始
*/
@Volatile
private var status: Int = 0

companion object {
fun <T : Any> build(block: suspend Generater<T>.() -> Unit): Generater<T> {
val g = Generater<T>()
var c = object : Continuation<Unit> {
override val context: CoroutineContext
get() = EmptyCoroutineContext

override fun resume(value: Unit) {
g.status = -1
}

override fun resumeWithException(exception: Throwable) {
g.status = -1
throw exception
}
}
g.mContinuation.compareAndSet(null, block.createCoroutine(g, c))
g.status = 1
return g
}
}

suspend fun yield(t: T?) {
suspendCoroutine<Unit> {
values.set(t)
mContinuation.compareAndSet(null, it)
//Thread.sleep(100)
}
}

fun next(): T? {
while (true) {
if (status == -1) {
values.set(null)
break
}
//可以提到循环外面
if (status == 0) {
throw IllegalStateException("生成器未启动")
}
val c = mContinuation.getAndSet(null)
c ?: continue

synchronized(this) {
c.resume(Unit)
}
break
}
return values.get()
}

}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

fun main(vararg args: String) {
//声明生成器
var g = Generater.build {
yield(0L)
var i = 0L
var j = 1L
while (true) {
yield(j)
var next = i + j
i = j
j = next
}
}
//多线程访问
Thread {
for (i in 0..2)
println(Thread.currentThread().name + ":" + g.next())
}.start()

Thread {
for (i in 0..2)
println(Thread.currentThread().name + ":" + g.next())
}.start()

Thread {
for (i in 0..2)
println(Thread.currentThread().name + ":" + g.next())
}.start()

Thread {
for (i in 0..2)
println(Thread.currentThread().name + ":" + g.next())
}.start()

Thread {
for (i in 0..2)
println(Thread.currentThread().name + ":" + g.next())
}.start()

Thread {
for (i in 0..2)
println(Thread.currentThread().name + ":" + g.next())
}.start()

Thread {
for (i in 0..2)
println(Thread.currentThread().name + ":" + g.next())
}.start()

Thread {
for (i in 0..2)
println(Thread.currentThread().name + ":" + g.next())
}.start()
}