curric

View on GitHub

./curric/Concurrency/Threads/

Threads (The Java Approach)

Multithreading is a Java feature that allows concurrent execution of two or more parts of a program for maximum utilization of CPU. Each part of such program is called a thread.

There are three different types of Threads.

Creating and Starting Threads in Java

Threads are apart of the Java Standard Library in java.lang. To import threads, use import java.lang.Thread;

To create Threads, invoke the Thread constructor with the new keyword. There are 8 different Thread constructors.

The most common Thread constructor that you will use it the Thread(Runnable Thread)

In these next example, we will create a new thread that will print the current Thread’s name and ID.

Here we extend the Thread class to create our custom Thread.

import java.lang.Thread;

class ThreadDemo extends Thread {
  public void run() {
    System.out.println("Name: " + Thread.currentThread().getName() + ", ID: " + Thread.currentThread().getId());
  }
}

class Main {
  public static void main(String[] args) {
    int n = 8; // number of threads
    for (int i = 0; i < n; i++) {
      ThreadDemo t = new ThreadDemo();
      // we call the default constructor 
      // we dont need to supply a Runnable object as
      // run function is already defined inside ThreadDemo
      // and that function will be the target function
      // that will be called when the Thread starts
      t.start();
    }
  }
}

Output (all will look relatively like this)

Name: Thread-6, ID: 16
Name: Thread-4, ID: 14
Name: Thread-2, ID: 12
Name: Thread-5, ID: 15
Name: Thread-1, ID: 11
Name: Thread-7, ID: 17
Name: Thread-3, ID: 13
Name: Thread-0, ID: 10

Here we implement the Runnable Interface to achieve the same output

import java.lang.Thread;
import java.lang.Runnable;

class RunnableDemo implements Runnable {
  public void run() {
    System.out.println("Name: " + Thread.currentThread().getName() + ", ID: " + Thread.currentThread().getId());
  }
}

class Main {
  public static void main(String[] args) {
    int n = 8; // number of threads
    for (int i = 0; i < n; i++) {
      Thread t = new Thread(new RunnableDemo());
      // here we supply a Runnable in the one args constructor
      // the run function defined in the RunnableDemo class
      // will be used as the target run function called
      // when the thread is started
      t.start();
    }
  }
}

We can also use an anonymous class

import java.lang.Thread;

class Main {
  public static void main(String[] args) {
    int n = 8; // number of threads
    for (int i = 0; i < n; i++) {
      Thread t = new Thread() {
        public void run() {
          System.out.println("Name: " + Thread.currentThread().getName() + ", ID: " + Thread.currentThread().getId());
        }
      };
      // here we create an anonymous thread class that 
      // overrides the run function
      // this run function will be used as the target function
      // when the Thread is started
      t.start();
    }
  }
}

Lastly, we can also use lambda syntax to create a new Thread

import java.lang.Thread;

class Main {
  public static void main(String[] args) {
    int n = 8; // number of threads
    for (int i = 0; i < n; i++) {
      Thread t = new Thread(
        () -> System.out.println("Name: " + Thread.currentThread().getName() + ", ID: " + Thread.currentThread().getId())
      );
      // the lambda supplied is a SAM type 
      // of the functional interface Runnable
      // and the lambda function is the run function
      // that will be used as the target function by the thread when started
      t.start();
    }
  }
}

All of these examples are valid methods of creating new threads. However, some are sytactically easier than others. (cough cough lambda cough cough)