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:
	-  there will usually be a large number of threads competing for a small number of shared
		resources (CPU cores, memory, even specific components of a given CPU core...);
	
 -  at a given moment in time, a thread that is "running" may actually not be able to progress
		because it is waiting for some resource to become available (e.g. data from a particular source,
		a lock on a particular file etc);
		
 -  on processors that support simultaneous multithreading (SMT), multiple threads can
			actually be "executed" simultaneously on a single CPU core as far as the programmer is
            concerned.
 
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:
	-  in recent years, greater advances in processor "power" have been made in the form
		of multicore/multiprocessor architecture rather than raw clock speed per se; to make the most
		of a computer's processing power, we are likely to need to distribute the work across
		multiple processors or cores;
	
 -  in other cases, the benefits of multithreading may have more to do with program flow and
		logic: in our example of a web server processing incoming simultaneous equests,
		processing different requests in separate threads makes the program easier to organise, even if
		the hardware it is running on is likely to have only a few cores compared to the number of
		concurrent requests.
 
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.
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).
	
	
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.