Writing Threaded Applications in Jython — PushToTest
Personal tools
You are here: Home Library How To Writing Threaded Applications in Jython

Writing Threaded Applications in Jython

Jython is a popular object oriented scripting language among software developers, QA technicians, and IT managers. It is also the scripting language in TestMaker and TestNetwork. In this article, Frank Cohen looks at Jython's ability to construct threaded multi-tasking software, shows the best practice to build scalable and thread-safe code, and points out how to avoid common mistakes and misunderstandings.

Feel free to share this document in its entirety with your 
friends and associates; However, this document remains 
© 2004 Frank Cohen. All rights reserved.

Jython and Threading

Jython is an object oriented scripting language that is popular with software developers, QA technicians, and IT managers. Jython is a 100% Java application. At runtime Jython scripts compile into Java bytecodes and run in the Java virtual machine. Jython classes are first class Java objects, so Jython can import any Java object on the classpath and call its methods. Jython gives Java developers the best of both worlds. Consequently, more and more test automation software, installation scripts, system monitoring code, and utility script code is being written in Jython.

Jython provides an easy environment to build objects. One of my first Jython scripts looked like this:

  class myclass:
    def setMyparam( self, myparam ):
      self.storeit = myparam

    def getMyparam( self ):
      return self.storeit

  a = myclass()
  a.setMyparam( "frank" )

  b = myclass()
  b.setMyparam( "lorette" )

  print "a.storeit =", a.getMyparam()
  print "b.storeit =", b.getMyparam()

This script implements a class name myclass. It has two methods, one to set a parameter and the second to get the stored value. Here is the output when I run the script:

  a = frank
  b = lorette

While this is straightforward enough, I envision using an object like myclass in a threaded application. These questions come to mind:

  • Which dictionary is the storeit variable stored?
  • Do I have to worry that some other call to another instance of myclass will get the storeit value from the wrong instance?
  • Is myclass thread safe?

Jython stores variables in dictionaries. Each new class gets its own dictionary when Jython instantiates the class. In myclass, self.storeit refers to the instance of storeit in the dictionary for the instance of myclass. As long as the script uses self.storeit then no other instance of myclass will get the self.storeit value. However, imagine the script includes a bug such as:

  def getMyparam ( self ):
      return storeit

In this example, I forgot to use self.storeit in the getMyparam method. Jython implements the equivalent of a Java Static class when myclass is defined in the script. This faulty print method retrieves the storeit value from the static class version of myclass and not from the instance of myclass referred to by a or b.

When multiple threads concurrently call setMyparam on the same instance of myclass, then it is anyone’s guess which thread uses the setMyparam method last and actually sets the final value of Myparam. This is commonly referred to as a race condition. Consider the following example program:

   import thread

  class myclass:
    def setMyparam( self, myparam ):
      self.storeit = myparam

    def getMyparam( self ):
      return self.storeit

  def runthenumbers( a, name ):
    for i in range(100):
      print name, ",", a.getMyparam()
      a.setMyparam( i * 2 )

  a = myclass()
  a.setMyparam( "frank" )

  thread.start_new_thread( runthenumbers, ( a, "Thread 1",) )
  thread.start_new_thread( runthenumbers, ( a, "Thread 2",) )

This script defines myclass with two methods: one to set a value and one to get a value. Then it defines a runthenumbers method that gets the value from a myclass object, prints it to the screen, and stores a new myclass value. The script then instantiates a myclass that will be referred to by a and sets the initial value to “frank�. Lastly, the script instantiates two concurrently running threads that operate on the instance of myclass.

When the script runs, both threads use the setMyparam and getMyparam method of myclass. It is likely that eventually one thread will interrupt the other when using setMyparam. In this case it anyone’s guess which thread’s call to setMyparam stores the final value since threads are meant to run concurrently by timesharing the system resources. In summary, this approach to coding a threaded application has these problems:

  • You have no way of telling the conditions of the threads: Have they started? Have they finished?
  • Multiple threads may try to call setMyparam concurrently. In the ensuing race condition, the last thread to call setMyparam wins. And there is no way to tell.

This is not to say that Jython cannot produce thread safe code. Jython does! However, there are multiple designs to create thread safe classes that avoid these problems.

The Many Ways To Thread An Application in Jython

Jython's ability to use Java objects introduces a variety of options when it comes to building threaded applications. This section describes four options and examines their relative merits and problems.

Python Threads

This example uses the Jython thread library. However, to overcome possible race conditions the script uses Jython's synchronized library to guarantee that only one thread can call a method at a time:

  import thread, synchronize

  class myclass:
    def setMyparam( self, myparam ):
      self.storeit = myparam
    setMyparam=synchronize.make_synchronized( setMyparam )

    def getMyparam( self ):
      return self.storeit
    getMyparam=synchronize.make_synchronized( getMyparam )

  def runthenumbers( a, name ):
    for i in range(100):
      print name, ",", a.getMyparam()
      a.setMyparam( i * 2 )

  a = myclass()
  a.setMyparam( "frank" )

  thread.start_new_thread( runthenumbers, ( a, "Thread 1",) )
  thread.start_new_thread( runthenumbers, ( a, "Thread 2",) )

In this example, make_synchonized uses the same technique as Java to synchronize method calls. Jython implements the synchronize library using this Java code:

  public static PyObject make_synchronized(PyObject callable)
  {
    return new SynchronizedCallable(callable);
  }

and SynchronizedCallable has a __call__ operator to call the argument callable's __call__ method in a synchronized block like this:

  synchronized(synchronize._getSync(arg))
  {
      return callable.__call__(arg);
  }

Python Threads provides an easy way in a Jython script to create a threaded application and synchronized thread safe methods within a class object. A newer Python technique uses the Threading library. Here is an example:

  import threading

  def greet( name ):
    print "greetings", name

  count = 0

  t = threading.Thread(
    target=greet,
    name="MyThread %d" % count,
    args=( "threading.Thread", )
    )

  t.start()

The new Python technique provides a slightly more Java-like feel to the syntax to create threads and provides a simple way to name a thread. Aside from those advantages I observe no performance or functional difference from the older Python technique.

Java Threads

This example uses the Java Thread library to implement a threaded example:

  from java.lang import Thread, Runnable

  class GreetJob( Runnable ):
      def __init__( self, name ):
          self.name = name
      def run( self ):
          print self.name

  count = 1

  t = Thread( GreetJob( "Runnable" ), "MyThread %d" % count )

  t.start()

Jython can also implement threads by extending the Java Thread class. Between these two techniques I have observed no differences in performance or functionality:

  from java.lang import Thread

  class GreetThread( Thread ):
      def __init__( self, name, count ):
          Thread.__init__( self, "MyThread %d" % count )
          self._name = name  # Thread has a 'name' attribute
      def run( self ):
          print self._name

  count = 2

  t = GreetThread( "Thread subclass", count )

  t.start()

I find it very unusual in a Python environment to have so many different ways to accomplish the same goal. Especially considering Python has a "one obvious way to do it" design principle. Therefore, next I describe what I believe to be the best practice to design Jython scripts that implement threads.

The Best Practice

Based on my experience writing threaded applications in Jython, using Java Threads and the Runnable interface is the best practice. The following Jython script implements the best practice for building threaded applications in Jython:

  from java.lang import Thread, Runnable
import synchronize

  class myclass( Runnable ):
    def __init__( self, myparam ):
      self.storeit = myparam

    def setMyparam( self, myparam ):
      self.storeit = myparam
    setMyparam=synchronize.make_synchronized( setMyparam )

    def printMyparam( self ):
      print "myclass: myparam =",self.storeit
    printMyparam=synchronize.make_synchronized( printMyparam )

    def run( self ):
      for self.i in range(5):
        self.printMyparam()

  count = 2

  a = myclass()
  a.setMyparam( "frank" )

  t = Thread( a, "MyThread %d" % count )
  t.start()

In summary, the best practice makes these points:

  • The above code example defines myclass to implement the Runnable interface from the Java Thread object. Runnable works best because it offers the thread management APIs to check status, set daemon thread status, and kill a thread.
  • I use the make_synchronized method of the synchronize library to make certain that only only one call to the method is possible at any given time.
  • The __init__ method creates the storeit object and sets the initial value. When the class is instantiated Jython calls the __init__ method on the instance of the new class so there is no need to synchronize __init__ because only the new instantiation of the class has access to it. __init__ is thread safe.

Joining Threads

An additional technique supported by the Java Thread technique is that threads may be joined. Your scripts use the current thread and one new thread and then "join" the threads so the current thread doesn't proceed until the new one finishes. Here's an example of that:

  import threading
  import time

  def pause(threadName, sleepSeconds):

     # create an attribute
     threading.currentThread.isDone = 0

     print "Thread %s is sleeping for %s seconds." \
     % (threadName, sleepSeconds)

     time.sleep(sleepSeconds)
     print "Thread %s is waking up." % threadName

     threading.currentThread().isDone = 1

  newThread = threading.Thread(name='newThread',\
  target=pause,args=('newThread',3))

  newThread.start()  

  # use the current thread too
  pause('currentThread',1) 

  # wait for newThread to finish
  newThread.join()

  # make sure they are both done
assert(newThread.isDone and threading.currentThread().isDone) 

  print "Both threads were done executing pause"

When running the script above I see the following output:

  Thread newThread is sleeping for 3 seconds.
  Thread currentThread is sleeping for 1 seconds.
  Thread currentThread is waking up.
  Thread newThread is waking up.
  Both threads were done executing pause

Java's Thread class also has a join method if you use Java's threads.

Where To Find Example Code

Download all the example code in this article at http://docs.pushtotest.com.

Where To Find Additional Information

Try these URLs for information that helped me write this article:

http://www.strakt.com/docs/eup02_threads_jacob.pdf

http://aspn.activestate.com/ASPN/Mail/Message/Jython-users/1051825

https://lists.sourceforge.net/lists/listinfo/jython-users

http://www.jython.org

http://www.pushtotest.com

About The Author

Frank Cohen is the "go to" guy for enterprises needing to test and solve problems in complex interoperating information systems, especially Web Services. Frank is founder of PushToTest, a test automation solutions business and author of Java Testing and Design: From Unit Tests to Automated Web Tests (Prentice Hall.) Frank maintains TestMaker, a free open-source utility that uses Jython to build intelligent test agents to check Web Services for scalability, performance and functionality. PushToTest Global Services customizes TestMaker to an enterprise's specific needs, conducts scalability and performance tests, and trains enterprise developers, QA technicians and IT managers on how to use the test environment for themselves. Details are at www.pushtotest.com. Contact Frank at fcohen@pushtotest.com.

Frank thanks to these people for providing content, ideas, and feedback for this article: Clark Updike (Clark.Updike@jhuapl.edu), Jeff Emanuel (jemanuel@lgc.com), Fred Sells (fred@adventistcare.org), and the many Jython fans at https://lists.sourceforge.net/lists/listinfo/jython-users.

Document Actions