Core Java

Java Thread Example

1. Introduction

Every Java program has at least one thread, the main thread. This is spun up by the Java Virtual Machine (JVM) when you run your code. Java is multithreaded which means it can utilize multiple threads concurrently. Thankfully, Java makes it easy to work with threads and multithreading. However, as developers or programmers, we need to take threading into account when designing solutions. In this article, we are going to take a look at threads and how they can be implemented.

You can also check this tutorial in the following video:

Java Threads Tutorial – video

2. Required Software

The only software we require for this example is Java. I’m using Java 8, java version “1.8.0_181”.

3. Thread API

While there have been a number of changes to the Thread API through the various Java versions over the years. The fundamentals have stayed the same. This Oracle Threads document shows the various methods available to us: https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html. Let us look at some commonly used methods

  • static Thread currentThread(): Returns a reference to the currently executing thread object
  • long getId(): Returns the identifier of this Thread
  • String getName(): Returns this thread’s name
  • int getPriority(): Returns this thread’s priority
  • Thread.State getState(): Returns the state of this Thread
  • boolean isAlive(): Tests if this thread is alive
  • void join(): Waits for this thread to die
  • void run(): If this thread was constructed using a separate Runnable object, then that Runnable object’s run method is called, otherwise, this method does nothing and returns.
  • void setPriority(int newPriority): changes the priority of this thread.
  • static void sleep(long millis): causes the currently executing thread to sleep temporarily for a specified number of milliseconds.
  • void start(): causes the thread to begin execution. The JVM then calls the run method of this thread.

What is important here is to see Deprecated methods. This article explains why some of these methods have been deprecated and why they are considered unsafe: https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

Spend a few minutes going through these docs to help you gain a better understanding of what is available, what is deprecated and why. This will give you a much better understanding of the Java Thread model and concurrency before we dive into the example.

4. Processes

In order to better contextualize Threads, we need to understand Processes and how the two are related. The Oracle Java SE tutorial has the following to say about threads and processes:

4.1 Processes and Threads

In concurrent programming, there are two basic units of execution: processes and threads. In the Java programming language, concurrent programming is mostly concerned with threads. However, processes are also important.

A computer system normally has many active processes and threads. This is true even in systems that only have a single execution core, and thus only have one thread actually executing at any given moment. Processing time for a single core is shared among processes and threads through an OS feature called time slicing.

It’s becoming more and more common for computer systems to have multiple processors or processors with multiple execution cores. This greatly enhances a system’s capacity for concurrent execution of processes and threads — but concurrency is possible even on simple systems, without multiple processors or execution cores.

https://docs.oracle.com/javase/tutorial/essential/concurrency/procthread.html

5. Concurrency

The Java tutorial also discusses concurrency. The merriam-webster definition of concurrency (https://www.merriam-webster.com/thesaurus/concurrency) provides the following synonyms: coexistence, coincidence, concurrence.

Given our newfound understanding of Threads and Processes from a Java perspective. The concept of Concurrency is much clearer. As of Java 5.0, the java.util.concurrent package was introduced.

Multithreading in java is the process of executing multiple threads simultaneously, concurrently.

Imagine a real-world example of a standalone desktop accounting application. There are numerous processes running concurrently. File read and write operations. Calculators and UI threads. Logging, caching….the list goes on. Now we really understand the benefits of Multithreading in Java.

6. The thread Lifecycle

A Google image search of java thread life cycle yields a number of varying examples. I think in order to better understand the thread lifecycle we need to look at it from a high-level perspective first. Think of it as a very basic overview of threads.

The conceptual Java thread lifecycle is depicted below, but this example is purposefully oversimplified.

Java Thread - Thread Lifecycle
Thread Lifecycle.

In order to better understand the thread lifecycle, we need to look at the Thread class.

6.1 Thread States

The java.lang.Thread class contains an enum for the Thread lifecycle states. A thread can only have one state at any point in its lifecycle.

Java Thread - Thread States.
Thread States.

The above diagram reflects the actual Thread States. The thread class API is available here: https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.State.html

A thread state. A thread can be in one of the following states:

NEW
A thread that has not yet started is in this state.
RUNNABLE
A thread executing in the Java virtual machine is in this state.
BLOCKED
A thread that is blocked waiting for a monitor lock is in this state.
WAITING
A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
TIMED_WAITING
A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
TERMINATED
A thread that has exited is in this state.

Oracle Java 8 API Docs

These states were first available in Java 1.5. As per the API docs. They represent JVM states and not operating system thread states.

Now that we understand states and the thread lifecycle, we can look at how to instantiate threads in Java.

7. Creating Threads

The examples below are based on the examples from the Java tutorial: https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

We create threads in Java in one of two ways. We can either implement the Runnable interface:

ThreadRunnableImpl.java

//Here we implement the Runnable interface
public class ThreadRunnableImpl implements Runnable {
	
	//this is the run method which is in the Runnable interface
	//and  we provide an implementation.
    public void run() {
        System.out.println("ThreadRunnableImpl thread is alive!");
    }
    //Here we create a new thread and start it.
    public static void main(String args[]) {
       (new Thread(new ThreadRunnableImpl())).start();

    }

}

Alternately we can subclass java.lang.Thread which implements the Runnable interface:

ExtendThread.java

//This example extends Thread which implements Runnable
public class ExtendThread extends Thread {

    public void run() {
        System.out.println("ExtendThread created this thread!");
    }

    //Notice here we don't call new Thread as we already extend Thread
    public static void main(String args[]) {
        (new ExtendThread()).start();
    }

}

Let us now look at an example that uses some of the Thread methods. The MyRunnable class has the run method that contains the logic to be implemented by the thread.

MyRunnable.java

public class MyRunnable implements Runnable {
	
	public void run(){
		for(int i=0;i<6;i++){
			System.out.println("Keep running for iteration: "+i);
			try{
				Thread.sleep(5000);
			} catch(InterruptedException e){
				e.printStackTrace();
			}
			System.out.println("Iteration completed for: "+i);
		}
	}
}

The ThreadMain class contains the logic to create the thread and interrupt.

ThreadMain.java

public class ThreadMain{
	public static void main(String args[]) throws InterruptedException{
		MyRunnable myRunnable = new MyRunnable();
		Thread thread = new Thread(myRunnable,"MYRUNNABLE");
		thread.start();
		
		thread.sleep(3000);
		System.out.println("Start :"+thread.getName());
		thread.interrupt();
		thread.join(1000);
		System.out.println("Last step :"+thread.getName());

	}
}

The result after the class execution is as shown below:

Keep running for iteration: 0
Start :MYRUNNABLE
java.lang.InterruptedException
        at java.lang.Thread.sleep(Native Method)
        at java.lang.Thread.sleep(Thread.java:943)
        at MyRunnable.run(MyRunnable.java:8)
        at java.lang.Thread.run(Thread.java:813)
Iteration completed for: 0
Keep running for iteration: 1
Last step :MYRUNNABLE
Iteration completed for: 1
Keep running for iteration: 2
Iteration completed for: 2
Keep running for iteration: 3
Iteration completed for: 3
Keep running for iteration: 4
Iteration completed for: 4
Keep running for iteration: 5
Iteration completed for: 5

8. Synchronization

When dealing with more than one thread, there is always a chance of concurrency issues. For example, two threads attempting to write to a single file. This could potentially have a disastrous outcome on the file contents. Perhaps even corrupting the file completely. This is known as a Race Condition. Where multiple threads are competing for the same resource.

Another potential pitfall is Memory Consistency Errors. For example, one thread could update a variables value and another thread would not be aware of this update. Instead, it would use the original value causing inconsistencies. I’m oversimplifying the examples, but you get the idea.

Java provides us with the volatile keyword to address this issue. When we require atomic operations involving multiple threads, we declare variables as volatile. See this document for further info regarding atomic operations and the volatile keyword: https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

At the method level, Java provides us with the synchronized keyword. A synchronized method only allows access by threads one at a time. Ensuring some defense against thread interference and memory inconsistency errors. Synchronized blocks differ from synchronized methods in that we must specify the object that provides the intrinsic lock. An intrinsic lock means that any other threads must wait until this lock is released by the initial thread before they have access to the object.

Here is the link to the Java Concurrency Tutorial: https://docs.oracle.com/javase/tutorial/essential/concurrency/index.html There is a lot more reading to be done on the topic of Threading in Java. This article and the tutorial are based on Java 8. There have been enhancements and improvements in later releases that have not been covered here.

9. Java Thread – Conclusion

You should have a clearer understanding of threading from a Java perspective. However, this is a very simple introduction and there are a number of topics that we have not covered. In fact when it comes to threading we have barely scratched the surface.

This article should get you off to a good start and there are many more excellent articles and code examples out there. It’s my hope that this article will pique your interest enough to get you to explore Multithreading and Concurrency further. We work with threads every day, but often don’t give a second thought to their implementation and the benefits or pitfalls thereof.

10. Download the Source Code

This was an Example of Java Threading.

Download
You can download the full source code of this example here: Java Thread Example

Last updated on Nov. 1st, 2019

Ed de Jongh

Ed has worked in the IT industry for over 20 years, gaining experience in programming, architecture and design. As a seasoned Solution Architect, he is passionate about advancing simplicity and elegance. In addition to solution design, he is also involved in development and integration. Outside of the office, enjoys anything on two wheels and being a dad.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button