-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
af8cebf
commit 3b998a5
Showing
25 changed files
with
484 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
plugins { | ||
kotlin("jvm") | ||
} | ||
|
||
val coroutinesVersion: String by project | ||
val jacksonVersion: String by project | ||
val okhttpVersion: String by project | ||
|
||
dependencies { | ||
implementation(kotlin("stdlib")) | ||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") | ||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion") // from string to object | ||
|
||
implementation("com.squareup.okhttp3:okhttp:$okhttpVersion") // http client | ||
|
||
testImplementation(kotlin("test-junit")) | ||
} |
20 changes: 20 additions & 0 deletions
20
m1l5-coroutines/src/main/kotlin/continuation/DecompileMePlease.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package continuation | ||
|
||
import kotlinx.coroutines.delay | ||
|
||
/** | ||
* How to decompile file in IDEA | ||
* | ||
* 1. Select class: build -> classes -> kotlin -> main -> continuation -> DecompileMePleaseKt.class | ||
* 2. Decompile: Tools -> Kotlin -> Decompile to Java | ||
*/ | ||
|
||
suspend fun myFunction() { | ||
println("Before") | ||
var counter = 0 | ||
|
||
delay(1000) // suspending | ||
|
||
counter++ | ||
println("After: $counter") | ||
} |
25 changes: 25 additions & 0 deletions
25
m1l5-coroutines/src/main/kotlin/continuation/HowItWorks.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package continuation | ||
|
||
import kotlinx.coroutines.delay | ||
import kotlinx.coroutines.launch | ||
import kotlinx.coroutines.runBlocking | ||
import kotlin.coroutines.suspendCoroutine | ||
|
||
fun main() = runBlocking { | ||
println("Start") | ||
|
||
// launch { | ||
// delay(1000) | ||
// repeat(5) { | ||
// delay(500) | ||
// println("Working....") | ||
// } | ||
// println("Done") | ||
// } | ||
// | ||
// suspendCoroutine<Unit> { continuation -> | ||
//// continuation.resume(Unit) | ||
// } | ||
|
||
println("Finish") | ||
} |
55 changes: 55 additions & 0 deletions
55
m1l5-coroutines/src/main/kotlin/continuation/PseudoDecompiledCode.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
//package continuation | ||
// | ||
//import kotlinx.coroutines.delay | ||
//import kotlin.coroutines.Continuation | ||
//import kotlin.coroutines.CoroutineContext | ||
// | ||
//fun myFunction(continuation: Continuation<Unit>): Any { | ||
// val continuation = continuation as? MyFunctionContinuation | ||
// ?: MyFunctionContinuation(continuation) | ||
// | ||
// var counter = continuation.counter | ||
// | ||
// when (continuation.label) { | ||
// 0 -> { | ||
// println("Before") | ||
// counter = 0 | ||
// continuation.counter = counter | ||
// continuation.label = 1 | ||
// if (delay(1000, continuation) == IntrinsicsKt.COROUTINE_SUSPENDED){ | ||
// return IntrinsicsKt.COROUTINE_SUSPENDED | ||
// } | ||
// } | ||
// 1 -> { | ||
// counter = (counter as Int) + 1 | ||
// println("After: $counter") | ||
// return Unit | ||
// } | ||
// else -> error("Impossible") | ||
// } | ||
// return Unit | ||
//} | ||
// | ||
//class MyFunctionContinuation( | ||
// val completion: Continuation<Unit> | ||
//) : Continuation<Unit> { | ||
// override val context: CoroutineContext | ||
// get() = completion.context | ||
// | ||
// var label = 0 | ||
// var result: Result<Any>? = null | ||
// | ||
// var counter = 0 | ||
// | ||
// override fun resumeWith(result: Result<Unit>) { | ||
// this.result = result | ||
// val res = try { | ||
// val r = myFunction(this) | ||
// if (r == IntrinsicsKt.COROUTINE_SUSPENDED) return | ||
// Result.success(r as Unit) | ||
// } catch (e: Throwable) { | ||
// Result.failure(e) | ||
// } | ||
// completion.resumeWith(res) | ||
// } | ||
//} |
33 changes: 33 additions & 0 deletions
33
m1l5-coroutines/src/main/kotlin/coroutinescope/BlockingVsSuspending.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package coroutinescope | ||
|
||
import kotlinx.coroutines.* | ||
import kotlin.coroutines.CoroutineContext | ||
|
||
fun CoroutineScope.suspendingCall(ctx: CoroutineContext) = | ||
launch(ctx) { | ||
println("Start_delay") | ||
delay(500) | ||
println("foo bar") | ||
} | ||
|
||
fun CoroutineScope.blockingCall(ctx: CoroutineContext) = | ||
launch(ctx) { | ||
runBlocking { | ||
println("Taking delay") | ||
delay(500) | ||
println("foo bar") | ||
} | ||
} | ||
|
||
@OptIn(DelicateCoroutinesApi::class) | ||
fun main() { | ||
println("Main start") | ||
val ctx = newSingleThreadContext("MyOwnThread") | ||
runBlocking { | ||
repeat(5) { | ||
suspendingCall(ctx) | ||
// blockingCall(ctx) | ||
} | ||
} | ||
println("Main end") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package dispatchers | ||
|
||
import kotlinx.coroutines.* | ||
|
||
fun main() = runBlocking { | ||
launch { // context of the parent, main runBlocking coroutine | ||
println("main runBlocking : I'm working in thread ${Thread.currentThread().name}") | ||
}.join() | ||
launch(Dispatchers.Unconfined) { // not confined to any thread -- will work with main thread now, and later on different | ||
println("Unconfined : I'm working in thread ${Thread.currentThread().name}") | ||
delay(50L) | ||
println("Unconfined : I'm working in thread ${Thread.currentThread().name} after delay()") | ||
}.join() | ||
launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher -> shared background pool of threads | ||
println("Default : I'm working in thread ${Thread.currentThread().name}") | ||
}.join() | ||
launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread | ||
println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}") | ||
}.join() | ||
} | ||
|
||
// When launch { ... } is used without parameters, it inherits the context (and thus dispatcher) from the CoroutineScope it is being launched from. In this case, it inherits the context of the main runBlocking coroutine which runs in the main thread. | ||
// | ||
// The Dispatchers.Unconfined coroutine dispatcher starts a coroutine in the caller thread, but only until the first suspension point. After suspension it resumes the coroutine in the thread that is fully determined by the suspending function that was invoked. The unconfined dispatcher is appropriate for coroutines which neither consume CPU time nor update any shared data (like UI) confined to a specific thread. | ||
// | ||
// On the other side, the dispatcher is inherited from the outer CoroutineScope by default. The default dispatcher for the runBlocking coroutine, in particular, is confined to the invoker thread, so inheriting it has the effect of confining execution to this thread with predictable FIFO scheduling. | ||
// The unconfined dispatcher is an advanced mechanism that can be helpful in certain corner cases where dispatching of a coroutine for its execution later is not needed or produces undesirable side-effects, because some operation in a coroutine must be performed right away. The unconfined dispatcher should not be used in general code. | ||
// | ||
// The default dispatcher that is used when no other dispatcher is explicitly specified in the scope. It is represented by Dispatchers.Default and uses a shared background pool of threads. | ||
// | ||
// newSingleThreadContext creates a thread for the coroutine to run. A dedicated thread is a very expensive resource. In a real application it must be either released, when no longer needed, using the close function, or stored in a top-level variable and reused throughout the application. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Easy | ||
|
||
`findNumberInList(numberToFind, listOfNumbers)` имитурет долгий поиска числа `numberToFind` в коллекции чисел `listOfNumbers`. Каждый | ||
запрос в метод заставляет остановить текущий поток на 2 секунды и после найти слово. Возвращает `-1` если число найти не удалось или | ||
возвращает самое число, если найдено. | ||
|
||
`foundNumbers` собирает все найденные числа в коллекци. | ||
В конце функции `dispatchers.main` в консоль выводится результат поиска: | ||
> Your number $number found! // если функция `findNumberInList` вернула число != -1 | ||
> "Not found number $toFind || $toFindOther" если не смог найти одно из запрошенных чисел | ||
**Задача**: необходимо реализовать код таким образом, чтобы поиск чисел в списке происходил паралелльно. Результатом решения будет | ||
вывод на печать результат поиска каждого запрошенного числа. | ||
Суммарное время выполнения текущего решения равна 4 секундам. В случае верного решения, скорость поиска должна увеличиться. | ||
|
||
**Условие**: использование корутин | ||
|
||
# Hard | ||
|
||
В данном примере происходит поиск слова со всеми его значениями из открытого api `https://api.dictionaryapi.dev` | ||
|
||
Данный api принимает в качестве аргумента `locale` и `слово` для поиска. | ||
Например: | ||
|
||
> https://api.dictionaryapi.dev/api/v2/entries/en/kill | ||
найдет слово `kill` в английском словаре. | ||
|
||
`HttpClient`, который реализует поиск не асинхронный. | ||
|
||
Текущий код синхронно ищет каждое слово в цикле. | ||
|
||
`FileReader` считывает из файла `words.txt` слова из которых формируется список уникальных слов для поиска. | ||
|
||
`findWords` принимает список слов для поиска и в цикле обращается к методу, который с помощью api ищет значение данных слов, сохраняя | ||
все это в объект `Dictionary` | ||
|
||
`Dictionary` содержит слово и массив всех найденных значений | ||
`Meaning` значение слова, содержит описание слова и примеры использования слова в реальных текстах. | ||
|
||
**Задача**: Асинхронно реализовать поиск значений каждого слова, меняя только код, а не `HttpClient` | ||
|
||
**Подсказки**: | ||
|
||
1. Может произойти ошибка поиска слова в api, поиск других слов не должен прерваться. Данное слово можно просто проигнорировать; | ||
2. Запрос в api можно реализовать в диспетчере `Dispatchers.IO` |
6 changes: 6 additions & 0 deletions
6
m1l5-coroutines/src/main/kotlin/homework/easy/findNumberInList.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package homework.easy | ||
|
||
fun findNumberInList(toFind: Int, numbers: List<Int>): Int { | ||
Thread.sleep(2000L) | ||
return numbers.firstOrNull { it == toFind } ?: -1 | ||
} |
5 changes: 5 additions & 0 deletions
5
m1l5-coroutines/src/main/kotlin/homework/easy/generateNumbers.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package homework.easy | ||
|
||
fun generateNumbers() = (0..10000).map { | ||
(0..100).random() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package homework.easy | ||
|
||
fun main() { | ||
val numbers = generateNumbers() | ||
val toFind = 10 | ||
val toFindOther = 1000 | ||
|
||
val foundNumbers = listOf( | ||
findNumberInList(toFind, numbers), | ||
findNumberInList(toFindOther, numbers) | ||
) | ||
|
||
foundNumbers.forEach { | ||
if (it != -1) { | ||
println("Your number $it found!") | ||
} else { | ||
println("Not found number $toFind || $toFindOther") | ||
} | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
m1l5-coroutines/src/main/kotlin/homework/hard/DictionaryApi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package homework.hard | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper | ||
import com.fasterxml.jackson.module.kotlin.readValue | ||
import homework.hard.dto.Dictionary | ||
import okhttp3.Response | ||
|
||
class DictionaryApi( | ||
private val objectMapper: ObjectMapper = jacksonObjectMapper() | ||
) { | ||
|
||
fun findWord(locale: Locale, word: String): Dictionary { // make something with context | ||
val url = "$DICTIONARY_API/${locale.code}/$word" | ||
println("Searching $url") | ||
|
||
return getBody(HttpClient.get(url).execute()).first() | ||
} | ||
|
||
|
||
private fun getBody(response: Response): List<Dictionary> { | ||
if (!response.isSuccessful) { | ||
throw RuntimeException("Not found word") | ||
} | ||
|
||
return response.body?.let { | ||
objectMapper.readValue(it.string()) | ||
} ?: throw RuntimeException("Body is null by some reason") | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
m1l5-coroutines/src/main/kotlin/homework/hard/HttpClient.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package homework.hard | ||
|
||
import okhttp3.OkHttpClient | ||
import okhttp3.Request | ||
|
||
object HttpClient : OkHttpClient() { | ||
fun get(uri: String) = | ||
Request.Builder().url(uri).build() | ||
.let { | ||
newCall(it) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package homework.hard | ||
|
||
enum class Locale(val code: String) { | ||
EN("en_US"), | ||
RU("ru") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package homework.hard | ||
|
||
internal const val DICTIONARY_API = "https://api.dictionaryapi.dev/api/v2/entries" |
9 changes: 9 additions & 0 deletions
9
m1l5-coroutines/src/main/kotlin/homework/hard/dto/Dictionary.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package homework.hard.dto | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
data class Dictionary( | ||
val word: String, | ||
val meanings: List<Meaning> | ||
) |
14 changes: 14 additions & 0 deletions
14
m1l5-coroutines/src/main/kotlin/homework/hard/dto/Meaning.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package homework.hard.dto | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
data class Meaning( | ||
val definitions: List<Definition> | ||
) | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
data class Definition( | ||
val definition: String, | ||
val example: String? = "" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package homework.hard | ||
|
||
import java.io.File | ||
|
||
fun main() { | ||
val dictionaryApi = DictionaryApi() | ||
val words = FileReader.readFile().split(" ", "\n").toSet() | ||
|
||
val dictionaries = findWords(dictionaryApi, words, Locale.EN) | ||
|
||
dictionaries.map { dictionary -> | ||
print("For word ${dictionary.word} i found examples: ") | ||
println(dictionary.meanings.map { definition -> definition.definitions.map { it.example } }) | ||
} | ||
} | ||
|
||
private fun findWords(dictionaryApi: DictionaryApi, words: Set<String>, locale: Locale) = // make some suspensions and async | ||
words.map { | ||
dictionaryApi.findWord(locale, it) | ||
} | ||
|
||
object FileReader { | ||
fun readFile(): String = | ||
File(this::class.java.classLoader.getResource("words.txt")?.toURI() ?: throw RuntimeException("Can't read file")).readText() | ||
} |
Oops, something went wrong.