When we create a new thread, it is independent of the Main thread, neither owns either. The OS will manage both of them.

Without intervention, threads do not obey order of execution that we may expect. Thread execution may not be in order and may be interleaved.

One element of thread cooperation provided by the Thread class is the ability to put a thread to sleep / pause the thread for a specified amount of time.

Stopping Threads

There are multiple ways to allow threads to come to a stop:

  • Deprecated Thread.stop() method, which leaves the application in an indeterminate state.
  • Using Thread.interrupt(), we can handle InterruptedException:
    public void run() {
        while (true) {
      	  try {
      		  Thread.sleep(1000);
      	  } catch (InterruptedException e) {
      		  return;
      	  }
        }
    }
  • Using a boolean:
    private boolean stopped;
     
    public void setStopped() {
        this.stopped = true;
    }
     
    public void run() {
        while (!this.stopped) {
      	  // execution
        }
    }
  • To ensure a thread exists when the Main thread exists, then we can make it a daemon thread by calling thread.setDaemon(true);

Coordinate Threads

Sometimes we may want to coordinate thread execution, we can use Thread.join() in order to wait for another or multiple threads to complete.

Thread thread;
thread.start();
// thread starts executing
 
thread.join();
// we wait for thread to terminate

JVM Thread States

The JVM defines its own set of thread states that do not typically reflect OS thread states:

  • NEW: thread that is yet to start
  • RUNNABLE: thread that is executing
  • BLOCKED: thread waiting for a monitor lock
  • WAITING: thread waiting indefinitely for another thread to perform a particular action
  • TIMED_WAITING: thread is waiting for another thread to perform action for up to a specified waiting time
  • TERMINATED: thread has exited