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

Table of Contents

 About This Book

 Installing JDK 1.4 on Windows 2000

 Installing JDK 1.5 on Windows XP

 Installing JDK 1.6 on Windows XP

 Execution Process, Entry Point, Input and Output

 Bits, Bytes, Bitwise and Shift Operations

 Managing Bit Strings in Byte Arrays

 StringBuffer - The String Buffer Class

 System Properties and Runtime Object Methods

Execution Threads and Multi-Threading Java Programs

 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

 ThreadGroup Class and "system" ThreadGroup Tree

 Synchronization Technique and Synchronized Code Blocks

 Deadlock Condition Example Programs

 Garbage Collection and the gc() Method

 References

 PDF Printing Version

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