Multithreading in Java enables the concurrent execution of multiple threads, allowing developers to harness the power of parallelism. It enhances the performance and responsiveness of applications by enabling tasks to run simultaneously. Let’s delve into the basics of multithreading in Java.
1. Creating Threads:
In Java, there are two main ways to create threads:
a. Extending the Thread
Class:
class MyThread extends Thread {
public void run() {
// Code to be executed by the thread
}
}
// Creating and starting the thread
MyThread myThread = new MyThread();
myThread.start();
b. Implementing the Runnable
Interface:
class MyRunnable implements Runnable {
public void run() {
// Code to be executed by the thread
}
}
// Creating and starting the thread
Thread myThread = new Thread(new MyRunnable());
myThread.start();
2. The run
Method:
The run
method contains the code that will be executed by the thread. It is the entry point for the thread’s logic.
class MyRunnable implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getId() + " Value " + i);
}
}
}
3. Starting a Thread:
The start
method is used to initiate the execution of a thread. It internally calls the run
method.
Thread myThread = new Thread(new MyRunnable());
myThread.start();
4. Thread States and Lifecycle:
- New: The thread is in the new state before the
start
method is called. - Runnable: The thread is in the runnable state after the
start
method is called, waiting to get CPU time. - Blocked: The thread is in the blocked state when it is waiting for a monitor lock.
- Waiting: The thread is in the waiting state when it is waiting indefinitely for another thread to perform a particular action.
- Timed Waiting: The thread is in the timed waiting state when it is waiting for another thread to perform a particular action for a specified waiting time.
- Terminated: The thread is in the terminated state when its
run
method exits.
5. Thread Priority:
Threads can have priorities ranging from 1 to 10, where 1 is the lowest and 10 is the highest. The default priority is Thread.NORM_PRIORITY
(5).
Thread myThread = new Thread(new MyRunnable());
myThread.setPriority(Thread.MAX_PRIORITY);
6. Thread Synchronization:
Synchronization is crucial when multiple threads access shared resources to avoid data corruption and race conditions.
Using synchronized
Methods:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
}
7. Joining Threads:
The join
method is used to wait for a thread to complete its execution before proceeding.
Thread myThread = new Thread(new MyRunnable());
myThread.start();
myThread.join(); // Wait for myThread to finish
8. Daemon Threads:
Daemon threads are background threads that do not prevent the program from terminating.
Thread daemonThread = new Thread(new MyRunnable());
daemonThread.setDaemon(true);
daemonThread.start();
9. Thread Groups:
Thread groups provide a way to organize threads.
ThreadGroup group = new ThreadGroup("MyThreadGroup");
Thread thread1 = new Thread(group, new MyRunnable());
10. Interrupting Threads:
The interrupt
method is used to interrupt a thread.
Thread myThread = new Thread(new MyRunnable());
myThread.start();
myThread.interrupt();
Conclusion:
Understanding the basics of multithreading is essential for developing concurrent and efficient Java applications. By creating threads, managing their lifecycle, and employing synchronization techniques, developers can unlock the power of parallel execution. Proper synchronization, coordination, and resource management are crucial aspects of writing robust and scalable multithreaded code in Java.