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
- Thread Class: The
Thread
class provides constructors and methods to create and perform operations on a thread. - Runnable Interface: The
Runnable
interface should be implemented by any class whose instances are intended to be executed by a thread. - 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:
- By Extending the Thread Class
- By Implementing the Runnable Interface
- 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 theThread
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 thestart()
method is called to begin execution.
- 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 theRunnable
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 aThread
object is created withmyRunnable
as its target. Thestart()
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 therun()
method directly will not start a new thread. - Handling InterruptedException: Always handle
InterruptedException
when usingThread.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
- Introduction to Java
- Setting Up the Development Environment
- Basic Syntax and Structure
- Variables and Data Types
- Operators
Module 2: Control Flow
Module 3: Object-Oriented Programming
- Introduction to OOP
- Classes and Objects
- Methods
- Constructors
- Inheritance
- Polymorphism
- Encapsulation
- Abstraction
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
- Introduction to Multithreading
- Creating Threads
- Thread Lifecycle
- Synchronization
- Concurrency Utilities
Module 9: Networking
- Introduction to Networking
- Sockets
- ServerSocket
- DatagramSocket and DatagramPacket
- URL and HttpURLConnection