This is a creation in Article, where the information may have evolved or changed.
The most competitive language in Java this summer. About its syntax sugar is not elaborated here, after all, it can be sweet to death you.
The first thing to say is the association, the user-state sub-thread, lightweight, process--thread----.
Relationships and differences between processes, threads, and co-routines:
The process has its own independent heap and stack, neither sharing the heap nor sharing the stack, and the process is dispatched by the operating system.
Threads have their own separate stacks and shared heaps, shared heaps, non-shared stacks, and threads are also dispatched by the operating system (standard threads Yes).
The threads share the heap as a thread and do not share the stack, and the process is displayed by the programmer in the code of the coprocessor.
The benefits of the co-process are as follows:
1. Reduce the overhead of CPU thread context switching
2. Reduced memory consumption;
3. Improved CPU cache hit ratio;
4. Improve performance on the whole;
5. Increase the load capacity of the system without improving the hardware.
Requires very little stack memory (presumably 4~5kb), by default, the size of the line stacks is 1MB, a thread can turn on hundreds of thousands of of the threads, and the thread consumes far more memory overhead than the co-process.
Golang originally born to achieve the co-process, by the runtime self-management, a go keyword can be opened goroutine. It's perfect, but today's not about Golang.
In short, the co-process is cheap, cheap, efficient synonymous.
In Java, to support this high-performance process, through the third-party package to achieve Quasar,comsat,kilim
The above three bits are the jars that are currently available in Java that can quickly implement coroutines.
Quasar: by weaving in Java bytecode, changing bytecode results, to use, javaagent way
Comsat:quasar's packaging version provides lightweight packaging that can be used quickly.
Kilim: As with Quasar, you also need to weave in bytecode to use
But there is a problem, must be pre-annotated, the above can be compiled, but to the Linux environment, the need to pass the javaagent, because the bytecode is rewritten, unable to track specific problems. The process management is a big problem, will be thread kill, no reason to disappear, the author through the large Half-month experiment, found that they can not pass most of the environment, and therefore give up.
Kotlin.corouties
Kotlin.corouties is a really good API. Syntax simplification, and Golang's go keyword can be a spell. However, the current Kotlin API is experimental in nature, but has the capability to produce a production environment and is expected to be released in 1.1.5. Because Kotlin and Java can be mixed, so coroutines is a prerequisite for the next high concurrency knowledge points.
Kotlin.corouties Scheduler
The Commonpool Scheduler is implemented by default by means of Fork/join, and currently does not provide interfaces for custom implementations
Launch (Commonpool)
Represents common pool of shared threads as Coroutine dispatcher for compute-intensive tasks.
It Uses[java.util.concurrent.forkjoinpool]when available, which implements efficient work-stealing algorithm for its Queues, so every coroutine resumption are dispatched as a separate task even when it already executes inside the pool. When available, it wraps Forkjoinpool.commonpool and provides a similar the shared pool where not.
In other words, the kotlin is parallel scheduling, about Fork/join can also open a separate chapter, temporarily not table.
unconfined Scheduler, the default is the main thread scheduling, unrestricted start the process, once the association has slept or hung up, will start a new co-process
Launch (unconfined)
A Coroutine dispatcher That's not the confined to any specific thread.
It executes initial continuation of the Coroutine right here on the current call-frame
And let the coroutine resume in whatever thread that's used by the corresponding suspending function, without
Mandating any specific threading policy.
Note, that if you need your coroutine to is confined to a particular the thread or a thread-pool after resumption,
But still want-to-execute it in the current call-frame until its first suspension and then you can use
An optional [Coroutinestart] parameter in coroutine builders like [launch] and [async] setting it to the
The value of [coroutinestart.undispatched].
Threadpooldispatcher.newsinglethreadcontext Scheduler, single-thread scheduler
Launch (Newsinglethreadcontext ("Myownthread"))
Creates new Coroutine execution context with the a single thread and built-in [yield] and [delay] support.
All continuations is dispatched immediately when invoked inside the thread of this context.
Resources of this pool (it thread) is reclaimed when job of this context is cancelled.
The specified [name] defines the name of the new thread.
An optional [parent] job is specified upon creation.
Launch (Newfixedthreadpoolcontext (+, "Myownthread")) scheduler, specifying the number of threads for the scheduler
Creates new Coroutine execution context with the Fixed-size thread-pool and built-in [yield] and [delay] support.
All continuations is dispatched immediately when invoked inside the threads of this context.
Resources of this pool (its threads) was reclaimed when job of the this context is cancelled.
The specified [name] defines the names of the threads.
An optional [parent] job is specified upon creation.
By default please use all launch (Commonpool), there is a special restriction problem, consider other scheduler
Launch (Commonpool) asynchronous coprocessor Open
Async (Commonpool) synchronous co-opening
Official example of hello,world!, Welcome to the world of Kotlin
fun main(args: Array<String>) {
launch(CommonPool) { // create new coroutine in common thread pool
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello,") // main function continues while coroutine is delayed
Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}
Sleep in the Kotlin will not be able to pause the co-process, it is a big pit, which will be discussed later.
Launch starts the process, and executes directly by default, or explicitly
var job= launch(CommonPool)
if(job.isActive){
job.cancel()
}else{
job.start()
}
The job task can be executed as needed, whether it is alive, canceled, etc., and provides a series of APIs
There is a small matter, kotlin removed; it's an estimate that could spark a war.
Commonpool Scheduler
Delay will pause for 1 seconds to run,
Printlin is the Kotlin printing method, equivalent to System.out.printlin
Thread.Sleep This sentence can only pause the thread that initiates the process
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch(CommonPool) { // create new coroutine and keep a reference to its Job
delay(1000L)
println("World!")
}
println("Hello,")
job.join() // wait until child coroutine completes
}
Runblocking<unit> start a non-blocking task with no return value
Job.join () Wait for the completion of the co-process task
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch(CommonPool) {
doWorld()
}
println("Hello,")
job.join()
}
// this is your first suspending function
suspend fun doWorld() {
delay(1000L)
println("World!")
}
This talk suspend keyword, in order to code separation, otherwise you can only in launch (Commonpool) {} internal with delay to sleep the association, remove the suspend is unable to call the delay in other methods Sleep Association, direct compilation error.
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = List(100_000) { // create a lot of coroutines and list their jobs
launch(CommonPool) {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() } // wait for all jobs to complete
}
This example compared to engage, start the 100K, if you like the author, 2G of Memory slag machine may directly out-of-memory error, such as the author of 8G large memory, is no problem. Easy and enjoyable 500ms execution completed.
This example is also to show that the process of lightweight and powerful, thread do not say 100K, even if 10K, your CPU and memory minutes of explosion, can only restart.
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch(CommonPool) {
var nextPrintTime = 0L
var i = 0
while (isActive) { // cancellable computation loop
val currentTime = System.currentTimeMillis()
if (currentTime >= nextPrintTime) {
println("I'm sleeping ${i++} ...")
nextPrintTime = currentTime + 500L
}
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancel() // cancels the job
delay(1300L) // delay a bit to see if it was cancelled....
println("main: Now I can quit.")
}
There are too many examples of delay, one to speak alone. Started a co-worker task to calculate the current time, and then you will find that the IsActive property is built into the process, which is one of the three built-in properties within the thread that is only three. The other two for the context and coroutinecontext, but the context has been abandoned, presumably the author feels the context, lied bar, from this can also be found Kotlin will not arbitrarily delete the API, but by renaming, overloaded way to provide new.
IsActive: If the process is alive or the task is not completed, the state returns true and returns False if canceled or completed
The meaning of the example also clearly tells you that if the task has not been canceled within the delay time and has been calculated and printed three times I ' M sleeping, then the task is cancelled, the association is cancel. Main thread output Main:now I can quit
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch(CommonPool) {
try {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
} finally {
run(NonCancellable) {
println("I'm running finally")
delay(1000L)
println("And I've just delayed for 1 sec because I'm non-cancellable")
}
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancel() // cancels the job
delay(1300L) // delay a bit to ensure it was cancelled indeed
println("main: Now I can quit.")
}
This example does not cancel, run (noncancellable) +finally= Absolute execution of the code
Run (noncancellable) The internal start of a new process, and can not be canceled, overbearing president-like code
Run ... You can use Coroutinecontext in {} to interact with the previous level of the block code.
fun main(args: Array<String>) = runBlocking<Unit> {
withTimeout(1300L) {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
}
}
Repeat (1000): iterator, enter the number of times to iterate: 1000 times
Withtimeout (1300L) time 1.3 seconds.
This wiathtimeout is mainly to control the time-out of the association, to avoid the association, has been active. Although inexpensive, does not mean that the task will continue to execute, to the time of the timeout will be thrown directly exception
suspend fun doSomethingUsefulOne(): Int {
delay(1000L) // pretend we are doing something useful here
return 13
}
suspend fun doSomethingUsefulTwo(): Int {
delay(1000L) // pretend we are doing something useful here, too
return 29
}
fun main(args: Array<String>) = runBlocking<Unit> {
val time = measureTimeMillis {
val one = async(CommonPool, CoroutineStart.LAZY) { doSomethingUsefulOne() }
val two = async(CommonPool, CoroutineStart.LAZY) { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}
Three examples
Measuretimemillis: The execution time of the return code block is less than Java.
Coroutinestart: The execution mode of the coprocessor (both async and launch can be used)
LAZY
Lazy Loading
Default mode
Default-executes immediately according to its context.
ATOMIC
Coordinated execution according to its contextual principles (non-cancellation) plan.
Similar to [DEFAULT], but the process cannot be canceled until it starts executing.
Undispatched
Unassigned: Temporarily not understood use
println ("The answer is ${one.await () + two.await ()}")
Kotlin execution calculations can be computed together in a string
The. Await actually gets the value returned by the coprocessor, in the example 13 and 29
suspend fun doSomethingUsefulOne(): Int {
delay(1000L) // pretend we are doing something useful here
return 20
}
suspend fun doSomethingUsefulTwo(): Int {
delay(1000L) // pretend we are doing something useful here, too
return 20
}
// The result type of asyncSomethingUsefulOne is Deferred<Int>
fun asyncSomethingUsefulOne() = async(CommonPool) {
doSomethingUsefulOne()
}
// The result type of asyncSomethingUsefulTwo is Deferred<Int>
fun asyncSomethingUsefulTwo() = async(CommonPool) {
doSomethingUsefulTwo()
}
// note, that we don't have `runBlocking` to the right of `main` in this example
fun main(args: Array<String>) {
val time = measureTimeMillis {
// we can initiate async actions outside of a coroutine
val one = asyncSomethingUsefulOne()
val two = asyncSomethingUsefulTwo()
// but waiting for a result must involve either suspending or blocking.
// here we use `runBlocking { ... }` to block the main thread while waiting for the result
runBlocking {
println("The answer is ${one.await() + two.await()}")
}
}
println("Completed in $time ms")
}
runblocking{} is a synchronous non-blocking code block executor, can be unified to get the return value of coroutines, support generics and accept the return parameter, multiple or a single coprocessor once started we have to take the return value not only can use await, also can use runblocking
Var result= runBlocking<Int> {
Var resultint = one.await() + two.await()
Println("The answer is resultint="+resultint)
/ / Basic types can be written directly
Resultint
}
Println(result)
============================================================================
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = arrayListOf<Job>()
jobs += launch(Unconfined) { // not confined -- will work with main thread
println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
}
jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
}
jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
}
jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
}
jobs.forEach { it.join() }
}
Describes a number of schedulers
Launch(Unconfined)
Launch(coroutineContext): This scheduler can only be used inside runBlocking. Strictly speaking, it is not a scheduler. In the above, the internal coroutine continues to start the coroutine.
Launch(CommonPool)
Launch(newSingleThreadContext("MyOwnThread"))
Specific explanations see the opening instructions
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = arrayListOf<Job>()
jobs += launch(Unconfined) { // not confined -- will work with main thread
println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
delay(500)
println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
}
jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
delay(1000)
println("'coroutineContext': After delay in thread ${Thread.currentThread().name}")
}
jobs.forEach { it.join() }
}
println ("' unconfined ': After delay in thread ${thread.currentthread (). name}")
This sentence will be printed in the new process, because the process itself is delay
private val log = LoggerFactory.getLogger(X::class.java)
fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
fun main(args: Array<String>) = runBlocking<Unit> {
val a = async(coroutineContext) {
log.info("I'm computing a piece of the answer")
log("I'm computing a piece of the answer")
6
}
val b = async(coroutineContext) {
log.info("I'm computing another piece of the answer")
log("I'm computing a piece of the answer")
7
}
log.info("The answer is ${a.await() * b.await()}")
}
Here is the log: If you are a Lombok user, then unfortunately, Lombox now do not support in Kotlin use @slf4j or @log4j
Fun log (msg:string) = println ("[${thread.currentthread (). Name}] $msg")
This is an official example, it's best not to use
Private Val log = Loggerfactory.getlogger (X::class.java)
Just take it with loggerfactory as before.
fun main(args: Array<String>) = runBlocking<Unit> {
println("My job is ${coroutineContext.get(Job.Key)}")
println("My job is ${coroutineContext.get(Job)}")
println("My job is ${coroutineContext[Job]}")
}
Runblocking<unit> This old man, the old man itself is actually also coroutines start unexpectedly, surprised not surprise, meaning not unexpectedly. This design is the same as Golang, there is a unified runtime manager, but here is an explicit.
It is designed to be the biggest reason is blocking execution, within it can start multiple async coprocessor, and then work together to calculate a complex object, and then unified return to runblocking, external can directly receive
Let's talk about it today, delay it. Welcome Dabigatran Exchange About Kotlin.coroutines
QQ Group: 641163584
Next chapter, it should be next week.
Reprint please contact me authorized