Untangling Java concurrency

Java 101: Understanding Java threads, Part 4: Thread groups, volatility, and thread-local variables

Final concepts for improving Java application programming with Java threads

1 2 3 4 Page 4
Page 4 of 4
// ThreadDeathDemo.java
class ThreadDeathDemo
{
   public static void main (String [] args)
   {
      MyThreadGroup mtg = new MyThreadGroup ("My Group");
      new MyThread (mtg, "My Thread").start ();
   }
}
class MyThread extends Thread
{
   MyThread (ThreadGroup tg, String name)
   {
      super (tg, name);
   }
   public void run ()
   {
      System.out.println ("About to do something.");
      doSomething ();
      System.out.println ("Something done.");
   }
   void doSomething ()
   {
      doSomethingHelper ();
   }
   void doSomethingHelper ()
   {
      throw new MyThreadDeath (MyThreadDeath.REASON2);
   }
}
class MyThreadDeath extends ThreadDeath
{
   final static int REASON1 = 1;
   final static int REASON2 = 2;
   final static int REASON3 = 3;
   int reason;
   MyThreadDeath (int reason)
   {
      this.reason = reason;
   }
}
class MyThreadGroup extends ThreadGroup
{
   MyThreadGroup (String name)
   {
      super (name);
   }
   public void uncaughtException (Thread t, Throwable e)
   {
      if (e instanceof MyThreadDeath)
      {
          reportError (t, e);
          cleanup ();
      }
      super.uncaughtException (t, e);
   }
   void reportError (Thread t, Throwable e)
   {
      System.out.print (t.getName () + " unable to do something. Reason: ");
      switch (((MyThreadDeath) e).reason)
      {
         case MyThreadDeath.REASON1:
            System.out.println ("First reason.");
            break;
         case MyThreadDeath.REASON2:
            System.out.println ("Second reason.");
            break;
         case MyThreadDeath.REASON3:
            System.out.println ("Third reason.");
      }
   }
   void cleanup ()
   {
      System.out.println ("Cleaning up");
   }
}

ThreadDeathDemo's main thread executes main()'s byte-code instructions, which create a MyThreadGroup object and a MyThread object that groups into MyThreadGroup. The main thread then starts a thread associated with MyThread.

The MyThread thread enters its run() method, where it prints some text and calls the doSomething() method. That method subsequently calls doSomethingHelper(), which throws a MyThreadDeath object. (I subclass ThreadDeath so I can assign a reason for the death of a thread.) At some point, the thrown MyThreadDeath object results in a call to MyThreadGroup's uncaughtException(Thread t, Throwable e) method, which determines if a MyThreadDeath object was thrown. If so, calls are made to methods reportError(Thread t, Throwable e) and cleanup(), to print error information and perform cleanup operations, respectively. When run, ThreadDeathDemo produces the following output:

About to do something.
My Thread unable to do something. Reason: Second reason.
Cleaning up

Caution: ThreadDeath is a powerful tool for causing a thread to terminate its execution. However, this tool is dangerous, and is the reason Sun deprecated the stop() method. When a thread throws a ThreadDeath object, all locked monitors unlock as ThreadDeath propagates up the method-call stack. Objects protected by these monitors become accessible to other threads. If those objects are in an inconsistent state, a program can experience erratic behavior, a database or file can corrupt, and so on. However, if you know that the thread is not holding any locks, you can safely throw ThreadDeath.

Review

This article completes my coverage of threads by exploring thread groups, volatility, thread-local variables, timers, and ThreadDeath. You learned to use thread groups to group related threads, to use volatility to allow threads access to main-memory copies of shared field variables, to use thread-local variables to give threads their own independently initialized values, to use timers to schedule the execution of tasks either periodically or for a one-time execution, and to use ThreadDeath to let a thread prematurely exit from its run() method.

Next month I'll show you how to use packages to organize your classes and interfaces.

Jeff Friesen has been involved with computers for the past 20 years. He holds a degree in computer science and has worked with many computer languages. Jeff has also taught introductory Java programming at the college level. In addition to writing for JavaWorld, he has written his own Java book for beginners— Java 2 by Example, Second Edition (Que Publishing, 2001; ISBN: 0789725932)—and helped write Using Java 2 Platform, Special Edition (Que Publishing, 2001; ISBN: 0789724685). Jeff goes by the nickname Java Jeff (or JavaJeff). To see what he's working on, check out his Website at http://www.javajeff.com.

Learn more about this topic

  • Learn more about Java: See the complete listing for Jeff Friesen's Java 101 series -- archived on JavaWorld.
  • Also see the Java Tips series: More than five years of compiled tips from JavaWorld's expert readers.

1 2 3 4 Page 4
Page 4 of 4