Java Tutorials - Herong's Tutorial Notes
Dr. Herong Yang, Version 6.00

interrupt() - Method to Terminate Thread

This section provides a tutorial example on how to terminate running threads with the interrupt() method.

There are 3 ways to terminate a thread:

  • The thread has finished the work it is designed to do, and exits the run() method naturally.
  • The thread has received an interruption signal, while doing its work. It decides to not continue with work and exits the run() method. It may also decide to ignore the signal and continue to work.
  • The thread has been marked as daemon thread. When the parent thread who created this thread terminates, this thread will be forcefully terminated by the JVM.

The following program demonstrates all the 3 ways of terminating a thread. The program is design to work at a timer. It can be set to run for a given number of minutes. Once it started, the program creates 3 sub-threads:

  • One acts as a normal clock, starting with the current time.
  • One acts as a stop watch, starting from 0.
  • One acts as a count-down timer, starting from the amount of time the timer is set to.
/**
 * TimerThread.java
 * Copyright (c) 2002 by Dr. Herong Yang
 */
import java.util.*;
import java.text.*;
class TimerThread extends Thread {
   private static final int NORMAL_CLOCK = 1;
   private static final int COUNT_DOWN = 2;
   private static final int STOP_WATCH = 3;
   private int type; // type of clock
   private int c_millisecond, c_second, c_minute, c_hour;
   private static int remaining_minutes = 5;
   private static int clock_interval = 100; // in milliseconds < 1000
   public static void main(String[] a) {
      System.out.println("Normal clock Stop watch   Count-down");
      TimerThread normal_clock = new TimerThread(NORMAL_CLOCK);
      TimerThread count_down = new TimerThread(COUNT_DOWN);
      TimerThread stop_watch = new TimerThread(STOP_WATCH);
      stop_watch.setDaemon(true);
      normal_clock.start();
      count_down.start();
      stop_watch.start();
      while (count_down.isAlive()) {
         System.out.print(normal_clock.getClock()+" "+
            stop_watch.getClock()+" "+ count_down.getClock()+"\r");
         try {
            sleep(1);
         } catch (InterruptedException e) {
            System.out.println("Interrupted.");
         }
      }
      normal_clock.interrupt();
   }
   public TimerThread(int t) {
      type = t;
      if (type==NORMAL_CLOCK) {
         GregorianCalendar c = new GregorianCalendar();
         c_hour = c.get(Calendar.HOUR_OF_DAY);
         c_minute = c.get(Calendar.MINUTE);
         c_second = c.get(Calendar.SECOND);
         c_millisecond = c.get(Calendar.MILLISECOND);
      } else if (type==COUNT_DOWN) {
      	 c_hour = remaining_minutes/60;
      	 c_minute = remaining_minutes%60;
         c_second = 0;
         c_millisecond = 0;
      } else {
      	 c_hour = 0;
      	 c_minute = 0;
         c_second = 0;
         c_millisecond = 0;
      }
   }
   public void run() {
      while (!isInterrupted()) {
         try {
            sleep(clock_interval);
         } catch (InterruptedException e) {
            break; // the main thread wants this thread to end
         }
         if (type==NORMAL_CLOCK || type==STOP_WATCH) 
            c_millisecond +=clock_interval;
         else c_millisecond -= clock_interval;      
         if (c_millisecond>=1000) {
            c_second += c_millisecond/1000;
      	    c_millisecond = c_millisecond%1000;
         }
         if (c_second>=60) {
      	    c_minute += c_second/60;
      	    c_second = c_second%60;
         }
         if (c_minute>=60) {
      	    c_hour += c_minute/60;
            c_minute = c_minute%60;
         }
         if (c_millisecond<0) {
      	    c_second--;
            c_millisecond += 1000;
         }
         if (c_second<0) {
      	    c_minute--;
            c_second += 60;
         }
         if (c_minute<0) {
            c_hour--;
            c_minute += 60;
         }
         if (c_hour<0) {
            c_hour = 0;
            break; // end this thread 
         }
      }
   }
   private String getClock() {
      // returning the clock as a string of HH:mm:ss:SSS format
      GregorianCalendar c = new GregorianCalendar();
      c.set(Calendar.HOUR_OF_DAY,c_hour);
      c.set(Calendar.MINUTE,c_minute);
      c.set(Calendar.SECOND,c_second);
      c.set(Calendar.MILLISECOND,c_millisecond);
      SimpleDateFormat f = new SimpleDateFormat("HH:mm:ss:SSS");
      return f.format(c.getTime());
   }
}

Threads in this program will be terminated in the following sequence:

  • The count-down thread will be the first one to terminate, when its clock reaches the 0 value.
  • The main thread is constantly checking the status of the count-down thread by calling count_down.isAlive(). Once it detects the termination of the count-down thread, it will then send the interruption signal to the normal clock thread by calling normal_clock.interrupt().
  • The normal clock thread is constantly checking its interruption status by calling isInterrupted(). Once it received the interruption signal from the main thread, it will break the loop, terminate itself.
  • After sending the interruption signal to the normal clock signal, the main thread will also terminate itself.
  • The stop-watch thread will be forced to terminate by the JVM, after the main thread terminates, because it is created by the main thread, and marked as a daemon thread.

Please also note that:

  • The interruption signal may come to a thread, while it is in the middle of a sleep. When this happens, the sleep() call will be returned immediately with the InterruptionException. The thread should terminate itself quickly.
  • The clocks simulated in the threads are not accurate at all. The extra time spend on executing the statements other the sleep() statement is counted. You will see that the clock time from the normal clock thread is running slower than your real watch.
  • I am using the System.out.print() method with the '\r' character to keep the output text repeating at the line on the screen. This will make the output looks much more like a real clock.
  • The GregorainCalendar class is used in my program to me getting the current hour, minute, second and millisecond values, and formatting those values into a string. I have more notes on calendar classes in my other book on JDK.

Output of one execution of my program:

Normal clock Stop watch   Count-down
21:19:13:764 00:05:00:000 00:00:00:000

Sections in This Chapter

What Are Processes and Threads?

The "Thread" Class - Creating Thread Objects With Thread Sub Classes

The "Runnable" Interface - Creating Thread Objects with Runnable Objects

CPU Execution Time Shared by Multiple Threads

CPU Execution Time Shared by Multiple Threads - Test Output

Application Data Shared by Multiple Threads

Application Data Shared by Multiple Threads - Test Results

interrupt() - Method to Terminate Thread

Dr. Herong Yang, updated in 2008
interrupt() - Method to Terminate Thread