idiomatic-kotlin-course/notebooks/Multitasking.ipynb

869 lines
22 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "Al3t64xqN0DN3JmLKHOVn2",
"type": "CODE"
}
},
"outputs": [],
"source": [
"%use coroutines"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Три оси многозадачности"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "TawmM9V8by8RGHfhNv7D3m",
"type": "MD"
}
},
"source": [
"### Синхронный х однопоточный х неконкурентный "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "XzjwoelmODMg8pmaJRe1KK",
"type": "CODE"
}
},
"outputs": [],
"source": [
"repeat(10){\n",
" println(\"Line number $it\")\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "UuTmCNAMCpUAHaAwWVYJPy",
"type": "CODE"
}
},
"outputs": [],
"source": [
"import java.util.stream.*\n",
"\n",
"IntStream.range(0, 100).sum()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "f6DGHwBOIRvKuYjtxVRn0W",
"type": "MD"
}
},
"source": [
"### Синхронный х однопоточный х конкурентный"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "O1DPfMSAedOChaqU5JWXrU",
"type": "CODE"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"null\n",
"java.util.ConcurrentModificationException\n",
"\tat java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1095)\n",
"\tat java.base/java.util.ArrayList$Itr.next(ArrayList.java:1049)\n",
"\tat Line_0_jupyter.<init>(Line_0.jupyter.kts:6)\n",
"\tat java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)\n",
"\tat java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)\n",
"\tat java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)\n",
"\tat kotlin.script.experimental.jvm.BasicJvmScriptEvaluator.evalWithConfigAndOtherScriptsResults(BasicJvmScriptEvaluator.kt:122)\n",
"\tat kotlin.script.experimental.jvm.BasicJvmScriptEvaluator.invoke$suspendImpl(BasicJvmScriptEvaluator.kt:48)\n",
"\tat kotlin.script.experimental.jvm.BasicJvmScriptEvaluator.invoke(BasicJvmScriptEvaluator.kt)\n",
"\tat kotlin.script.experimental.jvm.BasicJvmReplEvaluator.eval(BasicJvmReplEvaluator.kt:49)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.InternalEvaluatorImpl$eval$resultWithDiagnostics$1.invokeSuspend(InternalEvaluatorImpl.kt:127)\n",
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)\n",
"\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)\n",
"\tat kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:277)\n",
"\tat kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:95)\n",
"\tat kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:69)\n",
"\tat kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)\n",
"\tat kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:48)\n",
"\tat kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.InternalEvaluatorImpl.eval(InternalEvaluatorImpl.kt:127)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.CellExecutorImpl$execute$1$result$1.invoke(CellExecutorImpl.kt:79)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.CellExecutorImpl$execute$1$result$1.invoke(CellExecutorImpl.kt:77)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.withHost(ReplForJupyterImpl.kt:758)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.CellExecutorImpl.execute(CellExecutorImpl.kt:77)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.execution.CellExecutor$DefaultImpls.execute$default(CellExecutor.kt:12)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.evaluateUserCode(ReplForJupyterImpl.kt:581)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.access$evaluateUserCode(ReplForJupyterImpl.kt:136)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl$evalEx$1.invoke(ReplForJupyterImpl.kt:439)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl$evalEx$1.invoke(ReplForJupyterImpl.kt:436)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.withEvalContext(ReplForJupyterImpl.kt:417)\n",
"\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.evalEx(ReplForJupyterImpl.kt:436)\n",
"\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor$processExecuteRequest$1$response$1$1.invoke(IdeCompatibleMessageRequestProcessor.kt:140)\n",
"\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor$processExecuteRequest$1$response$1$1.invoke(IdeCompatibleMessageRequestProcessor.kt:139)\n",
"\tat org.jetbrains.kotlinx.jupyter.execution.JupyterExecutorImpl$Task.execute(JupyterExecutorImpl.kt:42)\n",
"\tat org.jetbrains.kotlinx.jupyter.execution.JupyterExecutorImpl$executorThread$1.invoke(JupyterExecutorImpl.kt:82)\n",
"\tat org.jetbrains.kotlinx.jupyter.execution.JupyterExecutorImpl$executorThread$1.invoke(JupyterExecutorImpl.kt:80)\n",
"\tat kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)\n"
]
}
],
"source": [
"val list = (0..100).toMutableList()\n",
"\n",
"list.forEach {\n",
" if(it % 2 == 0) list.remove(it)\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "N3QIwvANEngnvMgsCVJatN",
"type": "CODE"
}
},
"outputs": [],
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "x9nGAXOgOlWxd4cu6Smio8",
"type": "MD"
}
},
"source": [
"### Синхронный х многопоточный х неконкурентный"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "lRJGB0cHhpjQTdRdGynG0G",
"type": "CODE"
}
},
"outputs": [],
"source": [
"val sum = IntStream.range(0, 100).parallel().sum()\n",
"\n",
"println(sum)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "1lLEGWWbB6qnFr1qjfSGpo",
"type": "CODE"
}
},
"outputs": [],
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "OTRLxfWLADkMoc9ViJfeEq",
"type": "MD"
}
},
"source": [
"### Асинхронный х однопоточный х неконкурентный"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "r1yVVtgMhexxzx7gGVmeIg",
"type": "CODE"
}
},
"outputs": [],
"source": [
"fun runLongTask(result: Int = 8): Int {\n",
" Thread.sleep(100)\n",
" println(\"Task complete: $result\")\n",
" return result\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "8YvIKfD1I7cfbiPRMpk0DC",
"type": "CODE"
}
},
"outputs": [],
"source": [
"import java.util.concurrent.*\n",
"\n",
"val executor = Executors.newSingleThreadExecutor()\n",
"\n",
"val future = executor.submit<Int> {\n",
" val result = runLongTask()\n",
" println(result)\n",
" result\n",
"}\n",
"\n",
"future.get()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "nyjKPayaltq8gBzq2bIP1c",
"type": "MD"
}
},
"source": [
"### Асинхронный х однопоточный х конкурентный "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "UreOIHJpXQYfkjeHOvf1Bq",
"type": "CODE"
}
},
"outputs": [],
"source": [
"interface Observable{\n",
" fun onChange(callback: (Int) -> Unit)\n",
"}\n",
"\n",
"val observable: Observable by lazy{ TODO() }"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "1in8iE7mL9m895XWUNh0Sl",
"type": "CODE"
}
},
"outputs": [],
"source": [
"val list: MutableList<Int> = mutableListOf<Int>()\n",
"\n",
"observable.onChange { \n",
" list.add(it)\n",
"}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "TczpOZrkCKogcT7x7XWAUT",
"type": "MD"
}
},
"source": [
"### Асинхронный х многопоточный х неконкурентный"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "YvgL8fFuneP9USjjnsfiQj",
"type": "CODE"
}
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "9NS1h5b5lJ0BEzieUt6xrr",
"type": "CODE"
}
},
"outputs": [],
"source": [
"val executor: ExecutorService = Executors.newFixedThreadPool(4)\n",
"\n",
"repeat(8){\n",
" executor.submit{\n",
" runLongTask(it)\n",
" }\n",
"}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "REBgToVc8iKIrODCWXPdZj",
"type": "MD"
}
},
"source": [
"### Синхронный х многопоточный х конкурентный"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "3AjItM8WtjFE9qJo9JvZFW",
"type": "CODE"
}
},
"outputs": [],
"source": [
"import kotlin.io.path.Path\n",
"import kotlin.io.path.writeText\n",
"\n",
"val file = Path(\"someFile.txt\")\n",
"\n",
"val data: List<String> = emptyList()\n",
"\n",
"data.stream()\n",
" .parallel()\n",
" .forEach { \n",
" file.writeText(it)\n",
" }"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "XDCp5EjIq8v6ABeo5q2K6S",
"type": "MD"
}
},
"source": [
"### Асинхронный х многопоточный х конкурентный"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "taOKUd5Gc9U6TuGVFZJvew",
"type": "CODE"
}
},
"outputs": [],
"source": [
"val cache = mutableMapOf<Int, Int>\n",
"\n",
"val consumer: (Int) -> Unit = TODO()\n",
"\n",
"\n",
"repeat(8){ i->\n",
" executor.submit{\n",
" val result = cache.getOrPut(i){\n",
" runLongTask(i)\n",
" }\n",
" consumer(result)\n",
" }\n",
"}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "bSK4aInljsXYinbOTNSLdc",
"type": "MD"
}
},
"source": [
"## Инструменты"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "qjWpglMy3eSM475ozgnDPA",
"type": "MD"
}
},
"source": [
"#### Thread"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "nEZ6jKJhVHhsjMvptTQ3rU",
"type": "CODE"
}
},
"outputs": [],
"source": [
"import kotlin.concurrent.*\n",
"\n",
"val t = thread {\n",
" runLongTask()\n",
"}\n",
"t.join()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "k35GcE4VUIMtrznZ0C3BmC",
"type": "CODE"
}
},
"outputs": [],
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "bX0GaqyAH6q7Max0Tky7DW",
"type": "MD"
}
},
"source": [
"#### Future"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "TVhCm0JtWiYFFqWYORxuya",
"type": "CODE"
}
},
"outputs": [],
"source": [
"val future = executor.submit<Int>{\n",
" runLongTask()\n",
"}\n",
"\n",
"future.get()\n",
"future.cancel(true)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "a5BY9U8m9OeZSSsS0yGRSZ",
"type": "MD"
}
},
"source": [
"#### CompletableFuture"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "2rchFZt5trGqzOCuU3aPvz",
"type": "CODE"
}
},
"outputs": [],
"source": [
"import java.util.concurrent.*\n",
"\n",
"val cf = CompletableFuture.supplyAsync{\n",
" runLongTask()\n",
"}\n",
"\n",
"val cf2 = cf.whenComplete{ res, _ ->\n",
" runLongTask(res - 1)\n",
"}\n",
"\n",
"val cf3 = cf.whenComplete{ res, _ ->\n",
" runLongTask(res + 1)\n",
"}\n",
"\n",
"cf2.join()\n",
"cf3.join()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "izHWuE5ZZo1hphjMmc7BHj",
"type": "MD"
}
},
"source": [
"#### Lock"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "JTXxcGnvTS36OVX6GkJfkK",
"type": "CODE"
}
},
"outputs": [],
"source": [
"import java.util.concurrent.locks.*\n",
"\n",
"val list = mutableListOf<Int>()\n",
"val lock = ReentrantLock()\n",
"\n",
"val cf4 = CompletableFuture.supplyAsync{\n",
" val res = runLongTask(4)\n",
" lock.withLock { \n",
" list.add(res)\n",
" }\n",
"}\n",
"\n",
"val cf5 = CompletableFuture.supplyAsync{\n",
" val res = runLongTask(5)\n",
" lock.withLock { \n",
" list.add(res)\n",
" }\n",
"}\n",
"\n",
"cf4.join()\n",
"cf5.join()\n",
"\n",
"list"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Reactive streams"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class A(val value: Int)\n",
"class B(val value: Int)\n",
"\n",
"val aFlow = flowOf<A>()\n",
"val bFlow = flowOf<B>()\n",
"\n",
"val combined = aFlow.zip(bFlow){ a, b->\n",
" a.value + b.value\n",
"}.debounce(2.seconds)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Actor"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sealed class Event {\n",
" class Open(val transactionId: Int): Event()\n",
" class Close(val tranactionId: Int): Event()\n",
"}\n",
"\n",
"fun interface Actor {\n",
" suspend fun receive(event: Event)\n",
"}\n",
"\n",
"val actor = object : Actor {\n",
" private var transaction: Int? = null\n",
" override suspend fun receive(event: Event) {\n",
" when (event) {\n",
" is Event.Open -> if (transaction != null) {\n",
" error(\"Transaction already open\")\n",
" } else {\n",
" transaction = event.transactionId\n",
" }\n",
" is Event.Close ->if (transaction != event.tranactionId) {\n",
" error(\"Wrong transaction id: ${event.tranactionId}\")\n",
" } else {\n",
" transaction = null\n",
" }\n",
" }\n",
" }\n",
"\n",
"}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "YDqoXAD2XEED9MSPRuMMzL",
"type": "MD"
}
},
"source": [
"## Сорта асинхронности"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "kb1ccsTMIZX3aacLF6gPrJ",
"type": "MD"
}
},
"source": [
"#### Callback"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "jZrkouEiPJnMCCpxTFlgVP",
"type": "CODE"
}
},
"outputs": [],
"source": [
"import java.net.*\n",
"import java.net.http.*\n",
"import java.net.http.HttpResponse.*\n",
"\n",
"val client: HttpClient = HttpClient.newHttpClient()\n",
"\n",
"val request : HttpRequest = HttpRequest.newBuilder()\n",
" .uri(URI.create(\"https://sciprog.center\"))\n",
" .GET().build()\n",
"\n",
"val regex = \"\"\"href=\\\"(.+\\.png)\\\"\"\"\".toRegex()\n",
"\n",
"client.sendAsync(request, BodyHandlers.ofString())\n",
" .thenApply{ it.body() }\n",
" .thenApply{ \n",
" val resources = regex.findAll(it).map{it.groupValues[1]}\n",
"\n",
" resources.forEach { resourceName->\n",
" val resourceRequest : HttpRequest = HttpRequest.newBuilder()\n",
" .uri(URI.create(\"https://sciprog.center$resourceName\"))\n",
" .GET().build()\n",
" client.sendAsync(resourceRequest, BodyHandlers.ofByteArray()).thenAccept{ resourceResponse ->\n",
" val bodyBytes = resourceResponse.body()\n",
" //do something with the body\n",
" }\n",
" }\n",
" resources\n",
" }\n",
" .thenAccept{ println(it.toList()) }\n",
" .join()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "7zwURNaHnaTgOTAZumDDcd",
"type": "MD"
}
},
"source": [
"#### Реактивные потоки"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"datalore": {
"hide_input_from_viewers": true,
"hide_output_from_viewers": true,
"node_id": "lPXl5Gkvu7CuhlhUV7YJab",
"type": "CODE"
}
},
"outputs": [],
"source": []
}
],
"metadata": {
"datalore": {
"base_environment": "default",
"computation_mode": "JUPYTER",
"package_manager": "pip",
"packages": [],
"report_row_ids": [],
"version": 3
},
"kernelspec": {
"display_name": "Kotlin",
"language": "kotlin",
"name": "kotlin"
},
"language_info": {
"codemirror_mode": "text/x-kotlin",
"file_extension": ".kt",
"mimetype": "text/x-kotlin",
"name": "kotlin",
"nbconvert_exporter": "",
"pygments_lexer": "kotlin",
"version": "1.9.23"
}
},
"nbformat": 4,
"nbformat_minor": 4
}