Parallelism:
Taking a task and splitting it up, so multiple CPUs can compute partial solutions in parallel to solve the task in less wall-clock time.
Concurrency:
Having a number of tasks that need to be arranged in a way that solves as many of them per $time_unit as possible.
Some parallelizable tasks:
* sorting an array
* inverting a matrix
* rendering graphics
Some examples for concurrency:
* processing incoming web requests
* making outbound calls to DB and/or other web services
* observe file system for changes
Parallel and concurrent problems have a lot in common, but also a number of distinctive properties:
* task origin and control
* resource use and coordination
* main metric
* use and number of threads
Let's juxtapose them.
Task origin and control:
In parallel computing, it's the algorithm / the solution that produces multiple tasks and dev is in control over their shape and number.
In concurrent computing, tasks emerge from the environment and are part of the problem.
Resource use and coordination:
Parallel tasks coordinate use of resources (e.g. CPU time or data structures).
Concurrent tasks compete over resources (e.g. I/O).
Main Metric:
Latency for parallelized tasks.
Throughput for concurrent tasks.
Use and number of threads:
In parallel computing, threads are an abstraction for CPU cores. Thread count is usually in the same order of magnitude as core count.
In concurrent computing, threads are an abstraction for tasks. Having one thread per task would be easiest.
The distinction isn't always clear cut (e.g. booting an app requires initializing plugins / latency-oriented [P] but thread per plugin/task [C]) and the styles can be nested (e.g. a web request [C] requires sorting a large array [P]), but it's important to differentiate them.
Java supports both approaches, e.g.:
* thread pools work for either
* parallel streams lean towards parallelism
* reactive leans toward concurrency
#ProjectLoom will greatly improve support for concurrent programming by allowing us to have one (virtual) thread per task.
Beyond that, Loom aims to introduce *structured* concurrency. More on that in the JEP draft (openjdk.java.net/jeps/8277129), the latest Newscast (), and an upcoming thread.
š
Here's the thread I threatened. š„ (I'll see myself out.)
#ProjectLoom's virtual threads will make high performance in concurrent systems attainable with much simpler code. But Loom aims for even more and wants to make the code clearer and more robust by introducing *structured concurrency*.
Here's what that's all about. š§µ
Important: This is about concurrency, not parallelism. See yesterday's thread šš¾ for a more detailed distinction, but the gist is that concurrency is about processing lots of tasks that the environment throws at your system at the same time, ideally with high throughput.
* splitting and joining concurrent subtasks in different methods/classes
* little support to compose error-handling, cancellation, ā¦ across subtasks
* threading structure is opaque to the runtime, which only sees independent threads
* ā¦
I'm no security expert and don't know how ubiquitous this vulnerability is, but if you use Log4J 2.x, you should probably update to 2.15.x and read these:
From compact record constructors to pattern matching, from generic wildcards to chaining predicates and comparators, from jpackage to jlink - here are 11 #Java tricks handpicked from dev.java. š§µ
(Musical version of this thread: )
0/11
A #record's *canonical* constructor has one arg per component but in its *compact* form, you don't have to list them. You also don't have to (in fact, can't) assign fields, just do the checks/reassignments you need, rest happens automatically.
Serialization works great with #records, no black magic needed! The guaranteed presence of constructor parameters and accessors makes serialization work with the object model and makes it easy to create reliable serializable records.
Here are 11 improvements you get when updating to #Java16 later today: from records and type patterns to `Stream`-additions and Unix domain sockets, from creating installers to more performance and observability. š§µšš¾
Express in a single line that a type is just a collection of data without need for encapsulation and let the compiler do the rest:
record Range(int low, int high) { }
That results in almost the same API as the attached class. *drops mic*
#2 Type Pattern Matching
This is actually two-for-one:
* first step into pattern matching
* type patterns with `instanceof`
With a type pattern you check whether a variable is of a certain type and, if so, create a new variable of that type, so you can use it without casting.
That's a guiding light of #ProjectAmber and record serialization is the first step. The Inside Java Podcast episode on that topic with Julia Boes and @chegar999 (inside.java/2021/03/08/podā¦) gives great insight into how it achieves that. š§µ
1/10
First, what's wrong with regular serialization? In short:
* extralinguistic mechanism (aka "magic")
* undermines encapsulation
* causes security issues
* hinders evolving code
* holds back new Java features
In long (and why it turned out that way), see attached thread.
Do you dream of "value types" in Java? So do I! Hence I was thrilled to see that Project Valhalla is slowly coming out of exploration with two draft JEPs.
Here's what they currently propose. š§µšš¾
(If you prefer video: https:/www.youtube.com/watch?v=WBvTilbh8S0&t=344s)
1/10
First, why value types? To bridge the divide between
* primitives (fast, no memory overhead) and
* reference types (abstraction, safety, identity)
As is, we sometimes have to choose between performance and design. And we often choose wrongly.