ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> Jython-users
Jython-users
[Jython-users] Writing Threaded Applications in Jython
by Frank Cohen other posts by this author
Mar 25 2004 7:11PM messages near this date
[Jython-users] hello | [Jython-users] Statement execfile()
As a contribution back to the Jython community, I wrote an article that 
describes the various options Jython users have to write threaded 
applications. The complete and formatted article is available on the 
PushToTest Web site at:

http://www.pushtotest.com/Docs/howto/jythonthreads.html

I have also copied the text of the article below. I am open to 
feedback, corrections, and additions. Hopefully this will be a living 
document as Jython grows.

My thanks goes to Clark Updike (Clark.Updike@jhuapl.edu), Jeff Emanuel 
(jemanuel@lgc.com), Fred Sells (fred@adventistcare.org) for providing 
feedback, comments, and help.

---

Writing Threaded Applications in Jython

Abstract:

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@[...].com.


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id70&alloc_id638&opÌk
_______________________________________________
Jython-users mailing list
Jython-users@[...].net
https://lists.sourceforge.net/lists/listinfo/jython-users

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved