Multithreading in Java

Multithreading is the ability of a program or an operating system to manage multiple threads of execution concurrently within a single process. In Java, multithreading is supported by the java.lang.Thread class and the java.util.concurrent package.

Here is an example of creating a new thread using the Thread class:

public class MyThread extends Thread {
  public void run() {
    System.out.println("Thread is running");
  }
}
public class Main {
  public static void main(String[] args) {
    MyThread myThread = new MyThread();
    myThread.start();
  }
}

In the above example, we have created a new class MyThread that extends the Thread class and overrides the run() method. We then create an instance of MyThread and start it using the start() method. The start() method causes the run() method to be executed in a new thread of execution.

Java also supports multithreading using the Runnable interface:

public class MyRunnable implements Runnable {
  public void run() {
    System.out.println("Thread is running");
  }
}
public class Main {
  public static void main(String[] args) {
    MyRunnable myRunnable = new MyRunnable();
    Thread thread = new Thread(myRunnable);
    thread.start();
  }
}

In the above example, we have created a new class MyRunnable that implements the Runnable interface and overrides the run() method. We then create an instance of MyRunnable and pass it to a new instance of the Thread class. We start the thread using the start() method.

Java also provides several mechanisms for synchronization and communication between threads. One of the most commonly used mechanisms is the synchronized keyword, which is used to create synchronized methods and blocks.

public class Counter {
  private int count = 0;
  public synchronized void increment() {
    count++;
  }
  public synchronized void decrement() {
    count--;
  }
  public synchronized int getCount() {
    return count;
  }
}
public class Main {
  public static void main(String[] args) {
    Counter counter = new Counter();
    Thread thread1 = new Thread(() -> {
      for (int i = 0; i < 1000; i++) {
        counter.increment();
      }
    });
    Thread thread2 = new Thread(() -> {
      for (int i = 0; i < 1000; i++) {
        counter.decrement();
      }
    });
    thread1.start();
    thread2.start();
    try {
      thread1.join();
      thread2.join();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println(counter.getCount());
  }
}

In the above example, we have created a Counter class with synchronized methods for incrementing, decrementing, and retrieving the count. We then create two threads that increment and decrement the count respectively. We start the threads and wait for them to complete using the join() method. We then retrieve the count and print it.

In summary, multithreading is an important feature of Java that allows multiple threads of execution to be run concurrently within a single process. Java provides several mechanisms for creating and managing threads, as well as for synchronization and communication between threads.