Java & Threads

Threads are essentially subprocesses1: informally, we can think of them as tasks that run "simultaneously" within a program. For example, a web server application may have a number of threads running at a given time, each responding to a different web page request. A graphics rendering application may have different threads running, each rendering a different portion of an image. A strategy game might have multiple threads running, each exploring different potential moves for an AI player to make.

When multiple threads are in progress, the computer's operating system and processor(s) between them determine how to actually distribute the threads among the available CPU resources. In a simple hypothetical case where there are two threads are running and there are two CPU cores available, we might suppose that the threads can literally run simultaneously, one on each core. But the reality is usually muchg more complex:

The complex process of allocating threads to available resources is generally termed thread scheduling.

Java threading APIs

Despite the above complexities, multithreading is a necessity in all but the simplest of applications:

Different applications, then, need to make different uses of multithreading. Because of these different uses, and as typical uses have evolved over time, a number of different threading APIs have evolved both in Java and in other modern programming langauges.

java.lang.Thread and associated classes

The Thread class and associated Runnable interface and other methods provide the lowest level API that the programmer generally needs to deal with. This is the most "traditional" form of thread programming and is essentially the API that has been around since the very first versions of Java. Java's Thread class, along with the simple thread methods and a few other associated classes (notably Runnable) provide very broad-level features such as methods for:

As mentioned, the Thread API is essentially a low-level API. There is generally a close mapping between a Java Thread object and an actual thread or process at the operating system level. Calls such as Thread.start(), Thread.sleep(), Object.notify() etc will generally map quite closely to underlying operating system calls. API does not define thread tasks in terms of logical concepts such as jobs, queues, time limits etc. It is herefore the keystone of thread programming, but not the be-all-and-end-all in complex multithreaded applications. In particular, it does little to help the programmer to organise thread tasks into other structures that might be required such as processing queues, task statuses and communication between subtasks.

For more information, see the Java Thread tutorial on the following page.

The Executor framework

In can be cumbersome to write complex multithreaded applications using the Thread API alone. Therefore, the Java executor framework allows threads and their tasks to be defined in more "logical", higher-level terms (e.g. "tasks" are "scheduled" or added to queues).

The Java Stream API

Even with the Executor framework, the task of splitting a given task into multiple parallel subtasks can be tedious. The Java Stream API simplifies this for a class of tasks that can be broadly categorised as divide and conquer. If the task can be organised into a "stream" of largely independent items that can be split into sub-streams, then turning the task into a multithreaded one can be as simple as replacing stream() with parallelStream(). (The reality of when this is actually possibly and beneficial can also be much more complex!)

Virtual threads

A new API named Project Loom aims to offer a programming model similar to the traditional Thread model but with improved performance. The idea is that threads presented to the programmer are actually "virtual" threads. Tasks executed on different virtual threads as far as the programmer is concerned can be switched in and out of a smaller number of actual threads, all by the JVM, without the overhead of operating system calls to achieve this switching.

Getting started with threads in Java

On the next page, we look at how to start using threads in Java. It is recommended you then look at the other APIs mentioned above if you are planning to work on more advanced and complex multithreaded applications in Java.

If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.

Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.