Home arrow Java arrow Page 2 - Understanding Deployment Frameworks
JAVA

Understanding Deployment Frameworks


Java games can be deployed using various types of deployment frameworks. This article helps you understand the three different kinds of deployment frameworks, and shows you how to deploy your games to all three types without having to recompile your code. It is excerpted from chapter two of Advanced Java Game Programming, written by David Wallace Croft (Apress; ISBN: 1590591232).

Author Info:
By: Apress Publishing
Rating: 4 stars4 stars4 stars4 stars4 stars / 6
April 10, 2008
TABLE OF CONTENTS:
  1. · Understanding Deployment Frameworks
  2. · Managing the Applet Animation Thread
  3. · Reading from a JAR File
  4. · Upgrading Clients with the Plug-In

print this article
SEARCH DEVARTICLES

Understanding Deployment Frameworks - Managing the Applet Animation Thread
(Page 2 of 4 )

What was once prescribed is now proscribed when it comes to starting and stopping applet animation threads. In the past, the lifecycle method implementations might have looked like this:

  public void start( )
  //////////////////////////////////////////////////////////////////////
  {
    animationThread = new Thread ( this );

    animationThread.start ( );
  }

  public void stop( )
  //////////////////////////////////////////////////////////////////////
  {
    animationThread.stop ( );
  }

Or even like this:

  public void start ( )
  //////////////////////////////////////////////////////////////////////
  {
    if ( animationThread == null )
    {
      animationThread = new Thread ( this );

      animationThread.start ( );
    }
    else
    { 
      animationThread.resume ( );
    }
  }

  public void stop ( )
  //////////////////////////////////////////////////////////////////////
  {
    animationThread.suspend ( );
  }

  public void destroy ( )
  //////////////////////////////////////////////////////////////////////
  {
    animationThread.stop ( );
  }

The problem with these techniques is that using thejava.lang.Threadclass methodsstop(),suspend(), andresume()can sometimes put an object in an inconsistent state or cause a deadlock. This can result in random side effects that are difficult to debug. For this reason, these methods are now deprecated and should not be used in almost all circumstances. I have seen strange bugs simply disappear as a result of replacing old code that usedThread.stop(). Please see the online article from Sun “Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated?”1

  public void start ( )
  //////////////////////////////////////////////////////////////////////
  {
   
stopRequested = false;

    animationThread = new Thread ( this );

    animationThread.start ( );
  }

  public void stop ( )
  ////////////////////////////////////////////////////////////////////// 
  {
   
stopRequested = true;
  }

  public void run ( )
  //////////////////////////////////////////////////////////////////////
  {
   
while ( !stopRequested )
    {
     
animate ( );
    }
  }

Instead of hard-stopping a thread, you can let it die gracefully by having it poll a boolean stop request flag in a loop as shown in the preceding code. Note that the animation thread does not stop immediately when the request is made, as the stop request flag is only checked once per loop iteration. This can cause a problem if thestart()method is called immediately after thestop()method but before the animation loop has had a chance to poll the flag. It is possible with this technique that with some bad luck and bad timing you might end up with two or more threads running simultaneously.

  public void start ( )
  //////////////////////////////////////////////////////////////////////
  {
   
animationThread = new Thread ( this );

    animationThread.start ( );
  }

  public void stop ( )
  //////////////////////////////////////////////////////////////////////
  {
   
animationThread = null;
  }

  public void run ( )
  //////////////////////////////////////////////////////////////////////
  {
   
Thread animationThread = Thread.currentThread ( );

    while ( animationThread == this.animationThread )
    {
      animate ( );
    }
  }

The preceding code addresses that issue. Here the test is not a shared boolean flag but rather whether the current thread is still the one that the applet instance has designated as the primary animation thread. This operation is performed using an identity comparison. Note that in therun()method,animationThreadis a local method reference andthis.animationThreadis an object instance reference. In the worst case, the old animation thread only overlaps the new animation thread for one more iteration before bowing out.

  public synchronized void start ( )
  //////////////////////////////////////////////////////////////////////
  {
   
stopRequested = false;

    if ( animationThread == null )
    {
      animationThread = new Thread ( this );

      animatonThread.start ( );
    }
    else
    {
     
notify ( );
    }
  }

  public synchronized void stop ( )
  //////////////////////////////////////////////////////////////////////
  {
   
stopRequested = true;

    animationThread.interrupt ( );
  }

  public void run ( )
  //////////////////////////////////////////////////////////////////////
  {
   
while ( animationThread != null )
    {
      try
      {
        animate ( );

        if ( stopRequested )
        {
          synchronized ( this )
          {
           
while ( stopRequested )
            {
             
wait ( );
            }
          }
        }
      }
      catch ( InterruptedException ex )
      {
     
}
    }
  }

  public synchronized void destroy ( )
  //////////////////////////////////////////////////////////////////////
  {
   
animationThread = null;

    stopRequested = false;

    notify ( );
  }

The preceding code demonstrates how to prevent old and new animation threads from overlapping even momentarily during the transition by relying upon a single thread that is suspended and resumed using a boolean flagstopRequested and theObjectclasswait()method. Note that the code uses
synchronization, which tends to slow things down. This should not be a major problem because no synchronization requests are within the main animation loop when the animation is not stopped.

Methodsstart(),destroy(), and part of methodrun() are synchronized because any thread that calls thenotify()orwait()method must be the owner of the object monitor. Methodstop()is synchronized because it modifies the shared variablestopRequested.

Note that thestop()method callsanimationThread.interrupt(). This is because theanimate()method in the loop might monitor the interrupted status to determine if it should exit early. It might check the status at successive steps in a lengthy animation-frame generation process. It definitely checks the status if it usesThread.sleep()to delay within theanimate()implementation to slow down the loop to a desired frame rate.

The animation loop exits when thedestroy()method dereferences theanimationThread. Note that the animation loop does not exit immediately whendestroy()is called but only upon the check at the beginning of the next loop iteration. This means that the loop could still be using resources in the next-to-last loop iteration for animation after thedestroy()method has completed. This is most likely to occur if the container calls thedestroy()method immediately after thestop()method. If you intend to add additional code to the precedingdestroy()method to de-allocate resources used during animation, you might need to place some of it at the end of therun()method instead.

Thetry/catchblock within the loop is used to catchInterruptedExceptions thrown either by theanimate()method or by thewait()method. Note that it will probably be thrown most of the time by theanimate()method as theanimationThread.interrupt()call is in thestop()method. Thestop()method is normally not called when the thread is already suspended on thewait().

Calling thestop()method without an intervening call tostart()advances the animation by exactly one frame. This is because thewait()throws anInterruptedExceptionand the loop then continues for half an iteration. It callsanimate()just once before stalling on thewait()command again. Normally, a lifecycle container does not callstop()twice in a row and this single frame advance feature was not planned when the code was designed. You might, however, find it useful nonetheless.

Because I believe that this last technique for animation-thread management is the most robust, I selected it for the design of the reusable animation library described in the following chapter.


blog comments powered by Disqus
JAVA ARTICLES

- Java Too Insecure, Says Microsoft Researcher
- Google Beats Oracle in Java Ruling
- Deploying Multiple Java Applets as One
- Deploying Java Applets
- Understanding Deployment Frameworks
- Database Programming in Java Using JDBC
- Extension Interfaces and SAX
- Entities, Handlers and SAX
- Advanced SAX
- Conversions and Java Print Streams
- Formatters and Java Print Streams
- Java Print Streams
- Wildcards, Arrays, and Generics in Java
- Wildcards and Generic Methods in Java
- Finishing the Project: Java Web Development ...

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials