In this section, we will explore how to create and manage threads in Java. Multithreading is a powerful feature that allows concurrent execution of two or more parts of a program to maximize the utilization of CPU. Java provides built-in support for multithreading through the java.lang.Thread class and the java.util.concurrent package.

Key Concepts

  1. Thread Class: The Thread class provides constructors and methods to create and perform operations on a thread.
  2. Runnable Interface: The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread.
  3. Thread Lifecycle: Understanding the different states of a thread (New, Runnable, Blocked, Waiting, Timed Waiting, and Terminated).

Creating Threads

There are two main ways to create a thread in Java:

  1. By Extending the Thread Class
  2. By Implementing the Runnable Interface

  1. Extending the Thread Class

When you extend the Thread class, you need to override the run() method. The run() method contains the code that constitutes the new thread.

Example

class MyThread extends Thread {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Thread: " + i);
            try {
                Thread.sleep(500); // Sleep for 500 milliseconds
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    }

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        t1.start(); // Start the thread
    }
}

Explanation

  • Extending Thread Class: MyThread extends the Thread class.
  • Overriding run() Method: The run() method is overridden to define the code that runs in the thread.
  • Creating and Starting Thread: An instance of MyThread is created, and the start() method is called to begin execution.

  1. Implementing the Runnable Interface

When you implement the Runnable interface, you need to implement the run() method. This approach is more flexible as it allows the class to extend another class.

Example

class MyRunnable implements Runnable {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Runnable: " + i);
            try {
                Thread.sleep(500); // Sleep for 500 milliseconds
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    }

    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread t1 = new Thread(myRunnable);
        t1.start(); // Start the thread
    }
}

Explanation

  • Implementing Runnable Interface: MyRunnable implements the Runnable interface.
  • Implementing run() Method: The run() method is implemented to define the code that runs in the thread.
  • Creating and Starting Thread: An instance of MyRunnable is created, and a Thread object is created with myRunnable as its target. The start() method is called to begin execution.

Practical Exercises

Exercise 1: Create a Thread by Extending the Thread Class

Task: Create a thread that prints numbers from 1 to 10 with a delay of 1 second between each number.

Solution:

class NumberThread extends Thread {
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println("Number: " + i);
            try {
                Thread.sleep(1000); // Sleep for 1000 milliseconds
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    }

    public static void main(String[] args) {
        NumberThread t1 = new NumberThread();
        t1.start(); // Start the thread
    }
}

Exercise 2: Create a Thread by Implementing the Runnable Interface

Task: Create a thread that prints the first 10 Fibonacci numbers with a delay of 1 second between each number.

Solution:

class FibonacciRunnable implements Runnable {
    public void run() {
        int n1 = 0, n2 = 1, n3;
        System.out.print(n1 + " " + n2); // Print first two numbers
        for (int i = 2; i < 10; i++) {
            n3 = n1 + n2;
            System.out.print(" " + n3);
            n1 = n2;
            n2 = n3;
            try {
                Thread.sleep(1000); // Sleep for 1000 milliseconds
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    }

    public static void main(String[] args) {
        FibonacciRunnable fibonacciRunnable = new FibonacciRunnable();
        Thread t1 = new Thread(fibonacciRunnable);
        t1.start(); // Start the thread
    }
}

Common Mistakes and Tips

  • Not Calling start() Method: Always use the start() method to begin thread execution. Calling the run() method directly will not start a new thread.
  • Handling InterruptedException: Always handle InterruptedException when using Thread.sleep().
  • Thread Safety: Be cautious about thread safety when multiple threads access shared resources.

Conclusion

In this section, we learned how to create threads in Java using two different approaches: extending the Thread class and implementing the Runnable interface. We also covered practical examples and exercises to reinforce the concepts. Understanding how to create and manage threads is crucial for developing efficient and responsive applications. In the next section, we will delve into the thread lifecycle and synchronization mechanisms to manage thread interactions effectively.

Java Programming Course

Module 1: Introduction to Java

Module 2: Control Flow

Module 3: Object-Oriented Programming

Module 4: Advanced Object-Oriented Programming

Module 5: Data Structures and Collections

Module 6: Exception Handling

Module 7: File I/O

Module 8: Multithreading and Concurrency

Module 9: Networking

Module 10: Advanced Topics

Module 11: Java Frameworks and Libraries

Module 12: Building Real-World Applications

© Copyright 2024. All rights reserved