In markdown format empty line is not placed after the code block. For example:
this block
should be followed by an empty line in markdown mode, while it is not (it formats correctly in wiki mode)
| // https://akarnokd.blogspot.ru/2017/09/rxjava-vs-kotlin-coroutines-quick-look.html | |
| // Abstraction | |
| import kotlinx.coroutines.experimental.* | |
| suspend fun f1(i: Int): Int { | |
| Thread.sleep(if (i != 2) 2000L else 200L) | |
| return 1 | |
| } | |
| suspend fun f2(i: Int): Int { |
| import java.util.concurrent.atomic.AtomicReference | |
| private val cache = object : ClassValue<AtomicReference<Any?>>() { | |
| override fun computeValue(type: Class<*>) = AtomicReference<Any?>() | |
| } | |
| /** | |
| * Caches the given expression statically. | |
| * | |
| * Use it like this: |
In markdown format empty line is not placed after the code block. For example:
this block
should be followed by an empty line in markdown mode, while it is not (it formats correctly in wiki mode)
| import kotlinx.coroutines.experimental.DefaultDispatcher | |
| import kotlinx.coroutines.experimental.channels.ReceiveChannel | |
| import kotlinx.coroutines.experimental.channels.consumeEach | |
| import kotlinx.coroutines.experimental.channels.produce | |
| import kotlinx.coroutines.experimental.delay | |
| import kotlinx.coroutines.experimental.runBlocking | |
| import kotlin.coroutines.experimental.CoroutineContext | |
| fun <T> ReceiveChannel<T>.debounce( | |
| wait: Long = 300, |
Котлин революционизирует асинхронное программирование. В версии 1.1 в языке появились корутины -- это свежий, отличных от других языков подход к проблеме написания асинхронного кода. Мы посмотрим на этот механизм как сверху -- чем он отличается от традиционных подходов таких как callbacks, futures, и async/await, так и изнутри -- как всё это устроено. Более того, Котлин код можно компилировать под JVM и запускать бок-обок с Java кодом. Несмотря на то, что в Java не предполагается ничего для работы с асинхронностью на уровне языка, а все решения сосередоточены в библиотеках и подразумевают превращение любой нетривиальной асинхронной бизнес-логики в месиво замыкаканий и вызовов различных комбинаторов, корутины Котлина можно интегрировать и с асинхронных кодом на Java, что мы увидим на примерах.
| // Inspired by http://akarnokd.blogspot.ru/2017/09/rxjava-vs-kotlin-coroutines-quick-look.html | |
| // Requires Kotlin 1.2.30 or later | |
| // Uses kotlinx.coroutines library | |
| import kotlinx.coroutines.experimental.* | |
| import kotlin.system.* | |
| suspend fun f1(i: Int): Int { | |
| println("f1 attempt $i") | |
| delay(if (i != 3) 2000 else 200) |
| import kotlinx.coroutines.experimental.channels.* | |
| import kotlinx.coroutines.experimental.* | |
| class DownloadQueue { | |
| private sealed class Msg { | |
| class Request(val name: String) : Msg() { | |
| val answer = CompletableDeferred<Unit>() | |
| } | |
| class Result(val name: String, val error: Throwable? = null) : Msg() | |
| } |
| import kotlinx.coroutines.experimental.* | |
| import kotlinx.coroutines.experimental.channels.* | |
| import kotlinx.coroutines.experimental.selects.* | |
| import java.util.concurrent.* | |
| // operator | |
| fun <T> ReceiveChannel<T>.distinctInTimeWindow(time: Long, unit: TimeUnit): ReceiveChannel<T> = produce { | |
| require(time > 0) | |
| consume { | |
| val source = this@distinctInTimeWindow |
| import java.util.concurrent.* | |
| fun main(args: Array<String>) { | |
| class DomainSpecificException : RuntimeException() | |
| val cf1 = CompletableFuture<Int>() | |
| val cf2 = CompletableFuture<Int>() | |
| val res = cf1.thenCompose { cf2 } | |
| cf1.whenComplete { _, err -> println("cf1: Completed with error = $err") } |
| import java.util.stream.Stream | |
| abstract class NodeScaffold<THIS : NodeScaffold<THIS>> { | |
| private val children: List<THIS>? = null | |
| fun children(): Stream<THIS> { | |
| return children!!.stream() | |
| } |