La différence entre le fil et la coroutine dans Kotlin
Est-il un langage spécifique de la mise en œuvre de Kotlin, qui se distingue des autres langues de la mise en œuvre de coroutines?
- Ce qui signifie que la coroutine est comme la lumière-poids de fil?
- Quelle est la différence?
- Sont kotlin coroutines effectivement en cours d'exécution en parallèle /en même temps?
- Même dans le système multi-core, il y a seulement une coroutine cours d'exécution à un moment donné (est-il juste?)
Ici, je suis de départ de 100000 coroutines, ce qui se passe derrière ce code?
for(i in 0..100000){
async(CommonPool){
//run long running operations
}
}
- soundcloud.com/user-38099918/coroutines-with-roman-elizarov parler de Coroutines dans Kotlin
Vous devez vous connecter pour publier un commentaire.
Depuis que j'ai utilisé coroutines seulement sur la JVM, je vais vous parler de la JVM en arrière-plan, il y a aussi des Kotlin Natif et Kotlin JavaScript mais ces backends pour Kotlin sont hors de ma portée.
Donc, nous allons commencer avec la comparaison de Kotlin coroutines à d'autres langues coroutines. Fondamentalement, vous devez savoir qu'il existe deux types de Coroutines: stackless et stackful. Kotlin implémente stackless coroutines - cela signifie que coroutine ne dispose pas de sa propre pile, et que le fait de limiter un peu ce que coroutine peut faire. Vous pouvez lire une bonne explication ici.
Exemples:
Cela signifie que coroutine dans Kotlin ne dispose pas de sa propre pile, il n'a pas de carte sur un thread natif, il ne nécessite pas de changement de contexte sur un processeur.
Thread - préventivement multitâche. (habituellement).
Coroutine - collaboration multitâche.
Thread - géré par l'OS (généralement).
Coroutine - géré par un utilisateur.
Ça dépend, vous pouvez exécuter chaque coroutine dans son propre thread, ou vous pouvez exécuter tous les coroutines dans un thread ou un niveau fixé de pool de threads.
Plus sur la façon de coroutines exécuter ici.
Non, voir la réponse précédente.
En fait, ça dépend. Mais supposons que vous écrivez le code suivant:
Ce code s'exécute instantanément.
Parce que nous devons attendre les résultats de
async
appel.Donc, nous allons résoudre ce problème:
Lorsque vous exécutez ce programme kotlin permettra de créer 2 * 100000 instances de
Continuation
, ce qui va prendre quelques dizaines de Mo de RAM, et dans la console, vous verrez des nombres de 1 à 100000.Donc permet de réécrire ce code de cette façon:
Que nous faisons maintenant? Maintenant nous allons créer seulement 100001 instances de
Continuation
, et c'est beaucoup mieux.Créé suite sera distribué et exécuté sur CommonPool (qui est une instance statique de ForkJoinPool).
throws SuspendExecution
et Kotlin desuspend
modificateur. Les détails de mise en œuvre sont très différents, bien sûr, mais l'expérience utilisateur est tout à fait similaire.Coroutine, comme un fil, représente une séquence d'actions qui sont exécutées simultanément avec d'autres coroutines (threads).
Un thread est directement liée à la thread natif dans l'OS (système d'exploitation) et consomme une quantité considérable de ressources. En particulier, il consomme beaucoup de mémoire pour sa pile. C'est pourquoi vous ne pouvez pas créer de 100k threads. Vous êtes susceptible de manquer de mémoire. La commutation entre les threads implique noyau de système d'exploitation répartiteur et c'est une jolie opération coûteuse en termes de cycles de CPU consommé.
Une coroutine, d'autre part, est purement un utilisateur de la langue de l'abstraction. Il n'a pas d'égalité des ressources natives et, dans le cas le plus simple, utilise seulement un nombre relativement petit objet dans le segment de la JVM. C'est pourquoi il est facile de créer de 100k coroutines. La commutation entre les coroutines n'implique pas de noyau de système d'exploitation à tous. Il peut être aussi bon marché que l'invocation d'une fonction régulière.
Une coroutine peut être en cours d'exécution ou suspendu. Une suspension coroutine est pas associé à un fil, mais l'exécution d'un coroutine s'exécute sur certains thread (à l'aide d'un fil est la seule façon d'exécuter quoi que ce soit à l'intérieur d'un processus du système d'exploitation). Si les différents coroutines fonctionnent toutes sur le même thread a donc ne peut utiliser qu'un seul PROCESSEUR dans un système multicœur) ou dans différents threads (et peuvent donc les utiliser plusieurs Processeurs) est purement dans les mains d'un programmeur qui est à l'aide de coroutines.
Dans Kotlin, l'envoi de coroutines est contrôlé via coroutine contexte. Vous pouvez en savoir plus sur, puis dans le
Guide de kotlinx.coroutines
En supposant que vous utilisez
launch
fonction etCommonPool
contexte de lakotlinx.coroutines
projet (qui est open source), vous pouvez examiner le code source ici:launch
est défini ici https://github.com/Kotlin/kotlinx.coroutines/blob/master/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Builders.ktCommonPool
est défini ici https://github.com/Kotlin/kotlinx.coroutines/blob/master/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CommonPool.ktLa
launch
juste crée de nouvelles coroutine, tandis queCommonPool
les dépêches de coroutines à unForkJoinPool.commonPool()
qui utilise plusieurs threads et donc s'exécute sur plusieurs Processeurs dans cet exemple.Le code qui suit
launch
invocation dans{...}
est appelé un suspension lambda. Quelle est-elle et comment la suspension des lambdas et les fonctions mises en œuvre (compilé) ainsi que de la bibliothèque standard de fonctions et de classes commestartCoroutines
,suspendCoroutine
etCoroutineContext
est expliqué à la correspondante Kotlin coroutines document de conception de.Executor
, il n'existe aucune relation entre ces deux?