Threads are expensive

There is a price to pay whenever we create a new thread. Each thread needs a new memory stack.

What if we simulate some work inside each thread by putting it to sleep?

In the following piece of code, we'll attempt to create 10,000 threads, each sleeping for a relatively short period of time:

val counter = AtomicInteger()
try {
for (i in 0..10_000) {
thread {
counter.incrementAndGet()
Thread.sleep(100)
}
}
} catch (oome: OutOfMemoryError) {
println("Spawned ${counter.get()} threads before crashing")
System.exit(-42)
}

Depending on your operation system, this will result in either OutOfMemoryError or the entire system becoming very slow. Of course, there are ways to limit how many threads are run at once, using the executors API from Java 5.

We create a new thread pool of a specified size:

// Try setting this to 1, number of cores, 100, 2000, 3000 and see what happens
val pool = Executors.newFixedThreadPool(100)

Now we would like to submit a new task. We're doing this by calling pool.submit():



val counter = AtomicInteger(0)

val start = System.currentTimeMillis()
for (i in 1..10_000) {
pool.submit {
// Do something
counter.incrementAndGet()

// Simulate wait on IO
Thread.sleep(100)

// Do something again
counter.incrementAndGet()
}
}

Then we need to make sure that the pool terminates, by using the following lines:

pool.awaitTermination(20, TimeUnit.SECONDS)
pool.shutdown()

println("Took me ${System.currentTimeMillis() - start} millis to complete ${counter.get() / 2} tasks")

Notice that it took us 20 seconds to complete. That's because a new task cannot begin until previous tasks woke up and completed their job. 

And that's exactly what happens in multithreaded systems, which is not concurrent enough.

In the next section, we'll discuss how coroutines try to solve this problem.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.34.226