Threads and Multitasking
While we are discussing historical imperatives, threading wouldn't have been as useful or popular without garbage collection. While creating a threaded system is still in the domain of the specialist, all programmers who develop for application servers are developing code to be run in a thread. Without garbage collection, minor memory leaks in a stand-alone application become much worse on an application with many threads (all quite possibly running the same code).
Did I mention that multi-tasking is still a rare thing only used by a few specialists in the field? This isn't only because it's harder than normal development, but also because there aren't many occasions where the additional expense of task switching is worth the benefits of appearing to do two things at once. The operative word here is 'appearing'. On a single processor desktop, only one thread can be doing anything at one time. Only on a multi-processor server can you hope that multiple threads will execute in parallel. Even then this isn't guaranteed as the CPU time must be shared between multiple programs, not just threads.
So, when is multi-tasking of value?
- Application Servers: where one server services multiple clients or browsers.
- Communications: where messages need to be received when they arrive even if an earlier one is still processing.
- Spawning: Running external programs and not having to wait until they complete.
- Housekeeping: Just like at home, collections of data get messier over time. Faster response times can be had by quickly changing and throwing your discarded clothes on the floor. You can then come back and clean up when you have spare time (and I certainly hope my wife isn't reading this). This is why garbage collection with all its complex overheads can provide more responsive systems than C/C++ with malloc/free. Don't clean up memory as you finish with it, leave it and wait until you have free time. Application software can be the same. I have a cache with an ageing feature. It holds data like a HashMap, but if it is more than X minutes old it is discarded. It is, of course, checked on retrieval, but what of the case where the data is never retrieved again. I have a separate housecleaning thread that walks through the list when the system is not doing anything else looking for out-of-date data and removing it. Such data is closed if it has a Closeable interface. This is very useful for caching connections since you don't want them held open indefinitely if they are not being used.
- Prioritised Processing: is a close relative to housekeeping. My object database system has threads for deleted records, indexing and reorganisation. When you ask to delete a record it is flagged and the call returns. A background thread actually deletes the record and frees the space. The same goes for indexing. This can be expensive with multiple indexes, but why delay the calling program?
- Scheduled Tasks: You don't really want everything to freeze waiting for a specific time or time interval do you? A classic example is displaying a clock on a gui application. Start a thread that waits 1 second then redisplays the clock before waiting again and you have a timepiece with a minimum of system impact.
The use of threads can be divided into two diametrically opposite groups. Application servers and communications are examples of making a single service appear committed while actually serving many masters. Spawning, housekeeping and prioritised processing are all examples of providing more responsiveness by deferring tasks to a less busy time.
The reason these two use groups both work well with Java lightweight threads is that they both involve more waiting than working. While one thread is waiting, others can be busy without appearing to slow anything down.
There's that word again: On desktop systems, it appears that appearance is everything.








0 Comments:
Post a Comment
<< Home