In Java, one of the fundamental approaches to creating concurrent execution paths is by extending the Thread class. By inheriting from Thread, a class acquires the capability to run as an independent unit of execution.
Defining a custom thread involves overriding the run() method. This method serves as the entry point for the new thread and contains the logic intended to run within that specific thread context.
Instantiating the subclass prepares the thread object, but it does not initiate the execution flow. To actually launch the thread, the start() method must be invoked. This signals the Java Virtual Machine (JVM) to call the run() method of that instance, effectively running the code in parallel with the main application thread. It is crucial to note that calling run() directly bypasses multithreading behavior and simply executes the code as a standard method call within the same calling thread.
public class WorkerTask extends Thread {
@Override
public void run() {
// Define the task to be executed by the thread
for (int i = 0; i < 50; i++) {
System.out.println(getName() + " is executing task step " + i);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
// Instantiate the custom thread classes
WorkerTask alpha = new WorkerTask();
WorkerTask beta = new WorkerTask();
// Assign specific names to identify threads in the output
alpha.setName("Alpha-Thread");
beta.setName("Beta-Thread");
// Initiate thread execution
alpha.start();
beta.start();
}
}Upon executing the code above, the output demonstrates context switching, where statements from "Alpha-Thread" and "Beta-Thread" appear interleaved. This confirms that the CPU is distributing time slices between the two active threads rather than finishing one loop before starting the other.