Java
Multithreading
Thread
Runnable
Concurrency

What's the difference between Thread start and Runnable run

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In Java, multithreading is essential for improving the efficiency of applications by allowing tasks to be executed concurrently. Two fundamental concepts in multithreading are the Thread class and the Runnable interface. While both are used to create and manage threads, they have distinct methods that are essential to understand: Thread.start() and Runnable.run(). This article delves into the differences between these methods, explaining their purposes and usage through technical explanations and examples.

Thread and Runnable in Java

Before diving into the differences, it's crucial to understand what Thread and Runnable represent:

  • Thread: A Thread is an independent path of execution through a program. The Thread class provides methods to start and manage the threads.
  • Runnable: Runnable is a functional interface with a single method, run(). It's designed to provide a standard way of defining tasks to be executed by threads.

Key Differences

Purpose

  • Thread.start():
    • The start() method is responsible for creating a new thread and making it eligible for execution.
    • It initiates the thread's run() method.
    • It is only available in the Thread class.
  • Runnable.run():
    • The run() method is designed to encapsulate the task to be executed within a thread.
    • It doesn't create a new thread on its own.
    • It is suitable primarily for defining the logic that will be executed asynchronously.

Behavior

  • Thread.start():
    • When invoked, a new call stack is allocated for the thread, and the run() method is called in that new thread.
    • Starting a thread more than once throws IllegalThreadStateException.
  • Runnable.run():
    • The run() method is called like a normal method, and it executes in the current thread stack.
    • It does not initiate a new thread.

Example

java
1public class ThreadExample {
2    public static void main(String[] args) {
3        // Using Thread class
4        Thread myThread = new Thread(new RunnableTask());
5        myThread.start(); // Starts a new thread
6
7        // Directly calling run() method
8        RunnableTask task = new RunnableTask();
9        task.run(); // Runs in the main thread
10    }
11}
12
13class RunnableTask implements Runnable {
14    @Override
15    public void run() {
16        System.out.println("Task is running in: " + Thread.currentThread().getName());
17    }
18}

Output (Example):

 
Task is running in: Thread-0
Task is running in: main
  • In the example, calling start() for myThread creates a new thread, while task.run() executes in the main thread.

Summary Table

FeatureThread.start()Runnable.run()
FunctionStarts a new threadExecutes task within the current thread without starting a new one
Thread AllocationAllocates a new call stack for the threadDoes not allocate a new call stack (runs in current stack)
Repeated CallsThrows IllegalThreadStateException if called more than onceCan be called multiple times without issues
Use CaseCreates a new path of executionEncapsulates thread execution logic without creating a new thread

Additional Details

Use Cases and Considerations

  • When to use Thread.start():
    • Use when you need to independently execute tasks that require separate call stacks.
    • Suitable for computationally intensive tasks that can be distributed across multiple cores.
  • When to use Runnable.run():
    • Use for defining the logic of tasks without managing threads yourself.
    • Often used in frameworks or APIs where the API itself will handle the thread management.

Best Practices

  • Prefer using Runnable with Thread or executors from the java.util.concurrent package, as they allow for better separation of task definition and execution.
  • Utilize higher-level concurrency constructs such as ExecutorService, ForkJoinPool for cleaner and more robust multithreading solutions.

In conclusion, understanding the difference between Thread.start() and Runnable.run() is critical for effective multithreading in Java. By adhering to best practices and leveraging the strengths of each approach, developers can create efficient, scalable, and maintainable multithreaded applications.


Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.