Java Threads Definitive Tutorial

Java Thread is a basic of a multithreading program.

Concurrency in Java is a really big topic.

It consists of:

  • Threads
  • Thread Pools
  • Futures
  • ThreadLocal
  • Atomics
  • Concurrent collections
  • Synchronizers

This article is the first part of Java concurrency topics.

I’ll give answers to the following interview questions:

  • How to create a thread in Java?
  • What is a Thread Lifecycle?
  • How to prioritize thread execution?
  • How to stop a thread in Java?
  • What is a daemon thread?
  • How to handle InterruptedException?
  • How to handle exceptions outside of the thread?

I’ll write a simple thread program in Java to show how does it work.

Using Threads in Java

Programmers are using threads in Java to execute a piece of code in an asynchronous way.

There are 2 ways how to create a thread in Java:

  • Create a child of  Thread class
  • Implement  Runnable interface

The 2nd one is a more flexible way because you don’t have inheritance restrictions.

Create a Sub-class of a Thread

Let’s implement a TransactionThread that extends Thread class.

Imagine it executes bank transaction.

It accepts transaction id via the constructor and I want to print it during execution.

Example:

You should override method  run() and put your code there.

I want to execute 10 concurrent transactions.

i variable is an id of the transaction.

Output:

As you can see threads were executed in a different order.

JVM doesn’t guarantee threads execution order.

Implement a Runnable interface

Another way to create a new thread is to implement Runnable interface.

It’s doing the same as in the example above.

Execution looks like this:

Output:

Again threads executed in a different order.

How to Create a Thread in Java 8

In general, it’s a combination of implementing Runnable interface and Java 8 lambda.

Example:

Looks even better than first two solutions, but it’s a little bit complicated to test piece of code inside of the thread.

If you have encapsulated code in separate class you can easily write unit tests for it.

I copied  i variable because local variables referenced from a lambda expression must be final or effectively final.

Java Thread Lifecycle

There are 6 possible thread states in Java.

New
Thread is created but not started yet.
Runnable
Thread is executing, but it may be waiting for system resources, e.g. processor.
Blocked
Thread is waiting for monitor lock to enter a synchronized block or method.
Waiting
Thread is waiting for another thread action. It can happen if you’re using:  Object.wait(), Thread.join() or  LockSupport.part() methods. For example. a thread called  Object.wait() on an object is waiting for another thread call  Object.notify() or  Object.notifyAll() on that object.
Timed Waiting
The same as waiting but with specified waiting time. The following methods can do that:  Thread.sleep()Object.wait(long)Thread.join(long)LockSupport.parkNanos()  and  LockSupport.partUntil()
Terminated
Execution is finished

So lifecycle can be the following:

  1. New
  2. Runnable
  3. Blocked, waiting or timed waiting
  4. Terminated

3rd point is optional.

How to Set Thread Priority

As I mentioned before JVM doesn’t guarantee threads execution order.

One way to impact an order is to specify a priority.

You can invoke method:

So threads with a higher priority are executed in preference to threads with lower priority.

Thread class defined 3 constants:

As you can see minimum priority is 1 and maximum is 10.

If you invoke  setPriority(int newPriority) method with out of the range value –  IllegalArgumentException will be thrown.

Max thread priority can’t be higher than thread group max priority as well.

How to Stop Thread

The preferable way to stop a thread in Java is to use isInterrupted() and  interrupt() methods of a  Thread class.

Example:

We have a code that executes all time while the thread is not interrupted.

I want to start a thread, wait a little bit until it’s working and then stop it.

So the mechanism is simple:

  • Use  isInterrupted() method inside of your thread to check is current thread interrupted or not
  • Invoke  thread.interrupt() when you want to stop a thread

What Is a Daemon Thread?

Your program will work until at least one thread is alive.

But what if I want to stop the program when the main thread is stopped?

You have to mark a thread as a daemon.

Example:

This program will never stop.

You should do it manually.

To fix it we need to set daemon as true:

Now the new thread is marked as a daemon and it will finish its work when the main thread will be finished.

How To Catch Exception From Another Thread

For example, you started a thread and you want to handle an exception that occurred inside.

You can do it using uncaught exception handler.

Example:

Thread throws an exception during execution.

We catch this exception in UncaughtExceptionHandler and print its message.

What Is a Java InterruptedException And How To Handle It?

This exception is thrown when a thread is waiting or sleeping and thread is interrupted during or before this process.

I found 287 methods that throw this exception in Java 9.

The most important methods that you should know is:

  • Object.wait()
  • Thread.sleep()
  • Thread.joint()

The best practice to handle it is to mark a current thread as interrupted.

Example:

Conclusion

I explained the most important information about threads in Java, but the most complicated part is synchronization between multiple threads.

I’ll write about it in one of the future articles.

I hope you’ve got answers to the most popular interview questions about threads in Java.

If not – ask questions in comments.

Scroll Up