Introduction
A thread is a sequence of programmed instructions. A program that is running can have 1 or more threads, one of them being the main thread. The main thread is the one with which a program starts and is created automatically, without the need of any code from the programmer. However, if more than one threads are needed, the programmer must create and manage the additional threads through code.
The main reasons for using multiple threads are to reduce the time needed to execute heavy CPU operations by dividing and assigning a program's tasks to multiple CPU cores (parallel computing), and to separate user-interactive parts of a program from background processes of that program, in order to always keep the user interface alive and prevent the user from noticing any lag.
Java implementation
In Java, the Thread class provides the necessary methods to create and run threads. There are two possible ways to declare a class as a thread:
1. Make the class extend the Thread class and override the run method.
public class MyThread extends Thread{
public void run(){
//Add thread instructions
}
}
The thread can be started by calling the start method of an instance of this class.
MyThread t = new MyThread();
t.start();
2. Make the class implement the Runnable interface and implement the run method.
public class MyThread implements Runnable{
public void run(){
//Add thread instructions
}
}
The thread can be started by instantiating a new Thread object with the constructor that takes an instance of a class that implements Runnable as an argument and calling its start method.
MyThread t = new MyThread();
Thread th = new Thread(t);
th.start();
Below is an example of a Java program that makes basic use of multiple threads. 5 instances of the class MyThread are created and run. Each instance of MyThread has a number of steps that need to be executed and a unique ID that is used to distinguish it from the other threads. At every step, each thread prints its progress to the output stream.
public class MyThread extends Thread{
private static int nextId = 1;
private int numSteps;
private int id;
public MyThread(int numSteps){
this.numSteps = numSteps;
id = nextId++;
}
public void run(){
for (int i = 1; i <= numSteps; i++){
//Print the progress of this thread
System.out.println("Thread with ID " + id + " is at step " + i + " out of " + numSteps + ".");
try {
//Pause for 10 milliseconds to let the other threads proceed
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread with ID " + id + " has stopped executing.");
}
}
public class Main {
public static void main(String[] args){
//Initialize and start 5 instances of MyThread class
MyThread t = new MyThread(5);
t.start();
t = new MyThread(4);
t.start();
t = new MyThread(6);
t.start();
t = new MyThread(4);
t.start();
t = new MyThread(5);
t.start();
}
}
The output of the program looks like:
Thread with ID 2 is at step 1 out of 4.
Thread with ID 5 is at step 1 out of 5.
Thread with ID 4 is at step 1 out of 4.
Thread with ID 1 is at step 1 out of 5.
Thread with ID 3 is at step 1 out of 6.
Thread with ID 5 is at step 2 out of 5.
...
Thread with ID 3 is at step 5 out of 6.
Thread with ID 5 has stopped executing.
Thread with ID 1 has stopped executing.
Thread with ID 3 is at step 6 out of 6.
Thread with ID 3 has stopped executing.
It is obvious that the threads are not executed serially. Instead, they are executed parallelly.
Conclusion
Threads are the basic tool for building concurrent programs. However, there are more topics related to concurrency that should be considered, like synchronization and liveness problems.
That's all. I hope it helps. Let me know of any questions.