The run() method contains the code that is executed inside the new thread. Once a thread is created, you can start it by calling the start() method.

Every thread has a name. you can create a thread with a custom name using Thread(String name) constructor. If no name is specified then a new name is automatically chosen for the thread.

The above example consists of a for loop which iterates over the messages array, prints the current message, waits for 2 seconds by calling Thread.sleep(), and then proceeds with the next iteration.

The first method, where you create a thread by extending from Thread class is very limited because once you extend your class from Thread, you cannot extend from any other class since Java doesn’t allow multiple inheritance.

So, In general, You should always use Runnable object to create a thread. This method is more flexible. It allows your class to extend from any other class. Also, you can use anonymous class syntax and Java 8’s lambda expression with Runnable to make your code more concise.

The waiting time for Thread.join() is equal to MIN(time taken for the thread to terminate, number of milliseconds specified in the method argument).

Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. - From Java doc.

sleep() method throws InterruptedException if any thread interrupts the current thread. InterruptedException is a checked exception and it must be handled.

The sleep() method provided by Thread class allows you to pause the execution of the currently executing thread for the specified number of milliseconds.

In this tutorial, we learned two ways of creating threads in Java applications. We also learned about Thread’s sleep() and join() methods. All the code snippets used in this tutorial can be found in my github repository.

Runnable interface is the primary template for any object that is intended to be executed by a thread. It defines a single method run(), which is meant to contain the code that is executed by the thread.

The join() method allows one thread to wait for the completion of the other. In the following example, Thread 2 waits for the completion of Thread 1 for 1000 milliseconds by calling Thread.join(1000), and then starts the execution -

Thread.currentThread() returns a reference to the thread that is currently executing. In the above example, I’ve used thread’s getName() method to print the name of the current thread.

Note that, instead of creating a class which implements Runnable and then instantiating that class to get the runnable object, you can create an anonymous runnable by using Java’s anonymous class syntax.

This is the second part of my tutorial series on Java Concurrency. In the first part, we learned the basics of concurrency, processes and threads. In this post, we’ll learn how to create new threads and run tasks inside those threads.

Also, If you follow good design practice, Inheritance is meant for extending the functionality of the parent class, but when you create a thread, you don’t extend the functionality of Thread class, you merely provide the implementation of run() method.

For creating a new thread, create an instance of the class that implements Runnable interface and then pass that instance to Thread(Runnable target) constructor.