The world of mainstream computing is changing rapidly these days. If you open the hood and look under the
covers of your computer, you'll most likely see a dual-core processor there. Or a quad-core one, if you have
a high-end computer.  We all now run our software on multi-processor systems. The code we write today and
tomorrow will probably never run on a single processor system: parallel hardware has become standard.  Not
so with the software though, at least not yet. People still create single-threaded code, even though it will
not be able to leverage the full power of current and future hardware.  Some developers experiment with
low-level concurrency primitives, like threads, and locks or synchronized blocks.  However, it has become
obvious that the shared-memory multi-threading approach used at the application level causes more trouble
than it solves. Low-level concurrency handling is usually hard to get right, and it's not much fun either.
With such a radical change in hardware, software inevitably has to change dramatically too. Higher-level
concurrency and parallelism concepts like map/reduce, fork/join, actors and dataflow provide natural
abstractions for different types of problem domains while leveraging the multi-core hardware.
