It is opt-in. If you're using Tokio then you can specify whether you want to use a single-threaded or multi-threaded runtime. Multi-threaded is "default" in the sense that if you just use `#[tokio::main]` then you get a multi-threaded runtime but you can also just do `#[tokio::main(flavor = "current_thread")]` to get a single threaded executor.
More to the point, even using a multi-threaded runtime won't spawn threads willy-nilly. It will default to using N worker threads (where N is the number of CPU cores available).
> It is opt-in. If you're using Tokio then you can specify whether you want to use a single-threaded or multi-threaded runtime. Multi-threaded is "default" in the sense that if you just use `#[tokio::main]` then you get a multi-threaded runtime but you can also just do `#[tokio::main(flavor = "current_thread")]` to get a single threaded executor.
Doing something extra to get a behavior different than default is the definition of opt-out my friend.
That argument doesn't hold up. Adding `#[tokio::main]` is opting in because it is that extra something that has to be done. Adding that line is opting in to the multithreaded runtime.
The willy-nilly was in regard to Java and more precisely the ecosystem, not the language itself. In Java I find it hard to have N worker threads, where N is the number of CPU cores available, because many common libraries spawn threads - willy-nilly I'd say.
I have not enough experience about the Rust ecosystem but I hope it will successfully avoid a similar fate.
More to the point, even using a multi-threaded runtime won't spawn threads willy-nilly. It will default to using N worker threads (where N is the number of CPU cores available).