Multithreading in Java

 ### Multithreading in Java


Multithreading in Java is a process of executing multiple threads simultaneously. A thread is a lightweight subprocess, the smallest unit of processing. Multithreading is used to perform multiple tasks concurrently to make the best use of the CPU.


#### Key Concepts


1. **Thread Class**

2. **Runnable Interface**

3. **Thread Lifecycle**

4. **Thread Methods**

5. **Synchronization**

6. **Inter-thread Communication**


#### 1. Thread Class


In Java, a thread can be created by extending the `Thread` class and overriding its `run()` method.


Example:

```java

class MyThread extends Thread {

    public void run() {

        for (int i = 1; i <= 5; i++) {

            System.out.println(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

    }

}

```


#### 2. Runnable Interface


A thread can also be created by implementing the `Runnable` interface and passing an instance of the implementing class to a `Thread` object.


Example:

```java

class MyRunnable implements Runnable {

    public void run() {

        for (int i = 1; i <= 5; i++) {

            System.out.println(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

    }

}

```


#### 3. Thread Lifecycle


A thread in Java can be in one of the following states:


- **New**: When a thread is created but not yet started.

- **Runnable**: When a thread is ready to run and waiting for CPU time.

- **Blocked/Waiting**: When a thread is waiting for a resource to be available or waiting for another thread to complete its task.

- **Timed Waiting**: When a thread is waiting for a specified period.

- **Terminated**: When a thread has completed its task.


#### 4. Thread Methods


Some commonly used thread methods include:


- **start()**: Starts the thread.

- **run()**: Contains the code that constitutes the new thread.

- **sleep(long millis)**: Causes the current thread to sleep for a specified time.

- **join()**: Waits for a thread to die.

- **yield()**: Causes the current thread to pause and allow other threads to execute.

- **interrupt()**: Interrupts a thread.

- **isAlive()**: Tests if the thread is alive.


#### 5. Synchronization


Synchronization is a mechanism to ensure that only one thread can access a resource at a time. It prevents thread interference and consistency problems.


##### Synchronized Method

```java

class Table {

    synchronized void printTable(int n) { // synchronized method

        for (int i = 1; i <= 5; i++) {

            System.out.println(n * i);

            try {

                Thread.sleep(400);

            } catch (InterruptedException e) {

                System.out.println(e);

            }

        }

    }

}


class MyThread1 extends Thread {

    Table t;

    MyThread1(Table t) {

        this.t = t;

    }

    public void run() {

        t.printTable(5);

    }

}


class MyThread2 extends Thread {

    Table t;

    MyThread2(Table t) {

        this.t = t;

    }

    public void run() {

        t.printTable(100);

    }

}


public class TestSynchronization {

    public static void main(String[] args) {

        Table obj = new Table();

        MyThread1 t1 = new MyThread1(obj);

        MyThread2 t2 = new MyThread2(obj);

        t1.start();

        t2.start();

    }

}

```


##### Synchronized Block

```java

class Table {

    void printTable(int n) {

        synchronized (this) { // synchronized block

            for (int i = 1; i <= 5; i++) {

                System.out.println(n * i);

                try {

                    Thread.sleep(400);

                } catch (InterruptedException e) {

                    System.out.println(e);

                }

            }

        }

    }

}


class MyThread1 extends Thread {

    Table t;

    MyThread1(Table t) {

        this.t = t;

    }

    public void run() {

        t.printTable(5);

    }

}


class MyThread2 extends Thread {

    Table t;

    MyThread2(Table t) {

        this.t = t;

    }

    public void run() {

        t.printTable(100);

    }

}


public class TestSynchronization {

    public static void main(String[] args) {

        Table obj = new Table();

        MyThread1 t1 = new MyThread1(obj);

        MyThread2 t2 = new MyThread2(obj);

        t1.start();

        t2.start();

    }

}

```


#### 6. Inter-thread Communication


Java provides a way for threads to communicate with each other using the `wait()`, `notify()`, and `notifyAll()` methods. These methods must be called from within a synchronized context.


Example:

```java

class Chat {

    boolean flag = false;


    public synchronized void Question(String msg) {

        if (flag) {

            try {

                wait();

            } catch (InterruptedException e) {

                System.out.println(e);

            }

        }

        System.out.println(msg);

        flag = true;

        notify();

    }


    public synchronized void Answer(String msg) {

        if (!flag) {

            try {

                wait();

            } catch (InterruptedException e) {

                System.out.println(e);

            }

        }

        System.out.println(msg);

        flag = false;

        notify();

    }

}


class T1 implements Runnable {

    Chat m;

    String[] s1 = { "Hi", "How are you?", "I am also doing fine!" };


    public T1(Chat m1) {

        this.m = m1;

        new Thread(this, "Question").start();

    }


    public void run() {

        for (int i = 0; i < s1.length; i++) {

            m.Question(s1[i]);

        }

    }

}


class T2 implements Runnable {

    Chat m;

    String[] s2 = { "Hello", "I am good, how about you?", "Great!" };


    public T2(Chat m2) {

        this.m = m2;

        new Thread(this, "Answer").start();

    }


    public void run() {

        for (int i = 0; i < s2.length; i++) {

            m.Answer(s2[i]);

        }

    }

}


public class Test {

    public static void main(String[] args) {

        Chat m = new Chat();

        new T1(m);

        new T2(m);

    }

}

```


#### Conclusion


Multithreading in Java allows for the concurrent execution of two or more threads, making it possible to perform complex tasks efficiently. Understanding how to create, manage, and communicate between threads, as well as how to synchronize them, is essential for building robust and responsive Java applications.

Comments

Popular posts from this blog

Advanced Java Concepts

Welcome

Java Introduction