Simple Java Thread Management (SJT.Mgmt)
||Applications without thread management.
Designed for daily trips to the grocery store, the stylish
Pacer was a veritable safety hazard and dropped from production.
||Applications with thread management.
Sensible, safe, and functional, with elegance and performance,
the Audi A6 is an incredible everyday car.
SJT.Mgmt is a very easy to use library for adding thread management in
Java applications. Thread management allows multi-threading without the cost
of running out of memory and straining the CPU. Parameters include initial,
max size, and workload throttling. The library comes from early
experience with JServ's lack of thread management, and recent posts to the
java developer forums.
Over the past several years, Audi has consistently produced cars with
simple lines, functional interiors, safety features, incredible road handling,
and impressive performance.
SJT.Mgmt endeavours to replicate those qualities in a Java threading library.
It provides simple lines ( a friendly programming interface), functional
interiors ( easy to read code ), safety features ( prevents running memory
errors and taxing CPU), road handling (versatility within various applications),
and impressive performance ( short lock scopes, improved memory requirements,
less threads moving from wait and ready states)
Multi-threading is often required in an application, but the usual step
in introducing threads into an application is often a bad experience . Spawning
threads without any sort of control will bring your application down, particularly
if its heavily used . The following are procedures in a multi-threading system:
- Every thread in a system fights for execution time.
- Memory is needed for each thread stack.
- The garbage collector (in Java) is another thread fighting for execution
time. Running at minimum priority, it may not free memory associated with
- Execution is halted for all but one thread in critical section of shared
- All dormant threads come to life and fight for possesion of a single
token during the notification process.
- All but one thread are placed back into a dormant state.
Most applications are either CPU intensive, I/O intensive, or Human intensive.
CPU Intensive applications are optimized by using multiple CPU hardware,
with each CPU sharing the work load. I/O intensive applications are often
waiting on slower resources, such as disks or network connections. Human
intensive applications are waiting on even slower manual operation, such
as key strokes, mouse movements, and coffee breaks.
SJT.Mgmt can help in all three types of applications, but is most appropriate
for a I/O intensive system. It is very appropriate for applications using
a SocketServer. However, it will definitely help in CPU and Human intensive
applications because of its simple implementation. It is not optimized
for the CPU intensive model as one work load is assigned to only one working
thread, rather than spread the load across multiple processors. Processor
balancing is slated for an upcoming release.
Why thread management
The primary reason for thread management is scalability and safety. Scalablity
is improved since more requests are serviced with no change in resources.
Safety is enhanced by protecting your application from reaching the maximum
Fear of the unknown! A system without thread management has an increased
number of unknown variants. But a system with thread management has controlled
and known variants: the number of running threads in a system is know, the
memory required for all thread stack is preset and known, the number of unwillfully
spawned threads is known, the number of calls to notify - at all times during
the running of your application - is known. Using thread management resolves
issues of the unknown.
In most cases, the advantages of thread management out weight the disadvantages.
- The number of threads running in your system is capped at a very
- The memory needed for total thread stack size is known and will not
- A fixed and known number of threads contend for execution time per
- Thread objects do not need to be constructed during run time.
- Calls to the inefficient notifyAll() will be limited to a strict number
of threads, opposed to unnecessarily notifying an unlimited number of threads.
NotifyAll() will call all threads waiting on an object lock -- only one
thread obtains the object lock while all other threads return to the wait
- The garbage collector does not need to mark and sweep dead thread
objects, in order to free memory.
- Additional object synchronization is required. Objects are placed
onto a collection of some sort, typically a queue, in order to await execution.
The queue itself must be synchronized.
- Working threads may block on a specific task forever, which will reduce
your effective working threads by a significant number, one/pool size. A
maintenance thread is required to check for blocked threads, and assumptions
must be made on expected execution timing.
In a very simplified and slightly revealing ( yet ultimately inconclusive)
test of a recursive square root equation SJT.Mgmt library was consistently
magnitudes faster than those using a spawning thread model.
Following is the outcome of a test involving one square root calculation
per client, with 1000 distinct client requests.
Spawned Threads: 984 ms
SJT.Mgmt WorkManager Non-blocking: 246 ms
SJT.Mgmt WorkManager Blocking: 268 ms
Environment was as follows:
SunOS sunnyboy 5.8 Generic_108528-14 sun4u sparc SUNW,UltraAX-i2
Which is a Solaris 8, 500 Mhz Sparc, 512 MB Ram
java version "1.3.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_01)
Java HotSpot(TM) Client VM (build 1.3.1_01, mixed mode)
Please conduct your own tests and come to a conclusion based on your application
Be aware of the -X memory options available with the JVM, which affords
the easiest and most effective performance increase. Effective because allocating
and freeing memory is the slowest operation for the JVM.
-Xms<size> set initial
Java heap size
-Xmx<size> set maximum
Java heap size
set java thread stack size
The default heap size is probably not optimal for your application.
The answer is to calculate needed memory requirements and test often. Set
the initial size equal to the max size if the architecture can afford the
memory, and the application can deal with a slower initial start-up.
java -Xms1M -Xms5M MyQuickTest
java -Xms10M -Xmx50M MyStableServer
java -Xms1000M -Xms1000M MyFatEJBServer
The default stack size may be fine for your application, as it is difficult
to determine the optimal size. If you choose to spawn threads, attempt to
slim down the stack size.
java -Xss128K MySpawningServer
In short when using the -X options avoid allocating new heap memory during
run time, and minimize the thread stack size as best possible.
All applications must be tested. With multi-threaded applications the importance
of testing is magnified. Objects can incorrectly access shared objects, threads
can remain dormant forever, tokens may never be released. Testing will determine
your point of failure; it will focus your attention on critical pieces of
faulty code, or prompt you to introduce preventive measures.
Use thread management when you have no control over your clients. If your
application is accepting connections from an unknown number of clients,
you need thread management. If your system is accepting clients over a public
domain then you need thread management. If you expect more than 40
threads per CPU running in your system concurrently, you most likely need
thread management. If your system is pushing its memory and CPU capability
you should introduce thread management.
Carefully test your application and use the simple -X options in all cases.
The following articles have good explanations of the tricky issues in multi-threading.
SJT.Mgmt uses Junit for testing code. Please download this library at
prior to compiling ours.
XML is a system to system language and has no value in configuration files
maintained by humans, hence you don't need ant for building.
There are two mailing lists hosted on sourceforge.net
One public list for general users,
One private list for contributors,
Caucho team for their thread management in their Resin Servlet engine,
well in advance of JServ, and making Servlets a viable technology.
Matt Welsh for his Nonblocking I/O for Java.
Audi for building the A4 and A6, the S4, and the OffRoad.
Graciously hosted by: