fbpx

Basics of Multithreading in Java: Unlocking Parallel Execution

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.