Java Thread Tutorial - Java Multiple Threads








The following code shows how to run Multiple Threads in a Program.

public class Main {
  public static void main(String[] args) {
    // Create two Thread objects
    Thread t1 = new Thread(Main::print);
    Thread t2 = new Thread(Main::print);
/*  w  w  w. j a v  a  2 s.  co  m*/
    // Start both threads
    t1.start();
    t2.start();
  }

  public static void print() {
    for (int i = 1; i <= 500; i++) {
      System.out.println(i);
    }
  }
}

The code above generates the following result.





Threads Synchronization

Two kinds of threads synchronizations are built into the Java programming language:

  • Mutual exclusion synchronization
  • Conditional synchronization

In mutual exclusion synchronization, only one thread is allowed to access a section of code at a point in time.

The conditional synchronization is achieved through condition variables and three operations: wait, signal, and broadcast.





Synchronized keyword

The synchronized keyword is used to declare a critical section which need synchornization. There are two ways to use the synchronized keyword:

  • To declare a method as a critical section
  • To declare a block of statements as a critical section

We can declare a method as a critical section by using the keyword synchronized before the method's return type.

public class Main {
  public synchronized void someMethod_1() {
    // Method code goes here
  }

  public static synchronized void someMethod_2() {
    // Method code goes here
  }
}

We can declare both an instance method and a static method as synchronized. a constructor cannot be declared as synchronized.

The following code illustrates the use of the keyword synchronized:

public class Main {
  public synchronized void someMethod_1() {
    // only one thread can execute here at a time
  }

  public void someMethod_11() {
    synchronized (this) {
      // only one thread can execute here at a time
    }
  }

  public void someMethod_12() {
    // multiple threads can execute here at a time
    synchronized (this) {
      // only one thread can execute here at a time
    }
    // multiple threads can execute here at a time
  }

  public static synchronized void someMethod_2() {
    // only one thread can execute here at a time
  }

  public static void someMethod_21() {
    synchronized (Main.class) {
      // only one thread can execute here at a time
    }
  }

  public static void someMethod_22() {
    // multiple threads can execute here at a time
    synchronized (Main.class) {
      // only one thread can execute here at a time
    }
    // multiple threads can execute here at a time
  }
}

wait() method

The call to the wait() method must be placed inside a synchronized method or a synchronized block.

The wait() method must be called on the object whose monitor the current thread has acquired.

notify() method

There is no way to wake up a specific thread in the wait set.

Example

public class Main {
  private static int myValue = 1;
// ww w.ja v a  2  s . c om
  public static void main(String[] args) {
    Thread t = new Thread(() -> {
      while (true) {
        updateBalance();
      }
    });
    t.start();
    t = new Thread(() -> {
      while (true) {
        monitorBalance();
      }
    });
    t.start();
  }

  public static synchronized void updateBalance() {
    System.out.println("start:" + myValue);
    myValue = myValue + 1;
    myValue = myValue - 1;
    System.out.println("end:" + myValue);
  }

  public static synchronized void monitorBalance() {
    int b = myValue;
    if (b != 1) {
      System.out.println("Balance  changed: " + b);
      System.exit(1); 
    }
  }
}

The code above generates the following result.

Example 2

The following code shows a un-synchronized version of the code above.

public class Main {
  private static int myValue = 1;
/*w w w.  ja v  a  2  s .  c o  m*/
  public static void main(String[] args) {
    Thread t = new Thread(() -> {
      while (true) {
        updateBalance();
      }
    });
    t.start();
    t = new Thread(() -> {
      while (true) {
        monitorBalance();
      }
    });
    t.start();
  }

  public static  void updateBalance() {
    System.out.println("start:" + myValue);
    myValue = myValue + 1;
    myValue = myValue - 1;
    System.out.println("end:" + myValue);
  }

  public static synchronized void monitorBalance() {
    int b = myValue;
    if (b != 1) {
      System.out.println("Balance  changed: " + b);
      System.exit(1); 
    }
  }
}

The code above generates the following result.