The status of Queue Threads (Threads for this
discussion) is relevant to scheduling.
Threads process a request and then look in the Wait Lists for the next request.
When the status of any Thread is 'busy', it is reasonable to assume that since a thread
is actively processing, this Thread or another Thread will process any request put into a
Wait List. It is also reasonable to assume that Threads with a status of 'notified'
or 'reactivated' will become active shortly and process the Wait Lists.
When a Thread remains in an active or about to be active state for an unreasonable
amount of time then something may be wrong. In such a case, marking the thread 'cancelled'
and then 'disabled' after even more elapsed time is a way of eliminating the Thread from
consideration during scheduling.
For a non performing Queue, rather than filling up all the Wait Lists with pending
requests and returning a "no Wait List available" message to the new request,
Tymeac rejects the request immediately with a "no thread available" message. The
"no Wait List available" message could mean, try again later. The "no
thread available" message means something is wrong. See also scheduling failures.
The Monitor Thread notifies system administrators when all Threads are 'disabled'.
An entry becomes 'disabled' by:
1. An unhandled or re-thrown exception in a Processing
Application Class.
Threads handle exceptions by marking the Thread 'disabled'.
2. When a user manually disables a thread in the Queue Thread
display/alter.
3. When the Thread detects Immediate Shut Down.
4. The Monitor Thread changes the status from Cancelled to
Disabled.
Tymeac keeps track of the time of seven events:
Timing depends on an interval of time.
For Tymeac the base interval (bi) is:
- the Monitor interval set at start up in either the Configuration
File or User Variables, or,
- one minute if the Monitor interval is less than one minute.
1. The time the Scheduler activates/reactivates a Queue Thread.
The maximum time allowable is 2(bi)
(two times
the base interval.)
2. The time a Thread enters a 'Thread Processing' status
(executing Tymeac code.)
The maximum time allowable is 2(bi)
(two times
the base interval.)
3. The time the Thread invokes the Processing Application Class.
This value is determined by the individual Queue, timeout
value.
When the value is zero then the system default is used. That default is
4(bi)
(four times the base interval.)
When that value is greater than zero, then the Queue's timeout value is used.
4. The time the Thread calls the Scheduler (for the Output Agent
Queue).
The maximum time allowable is 1(bi)
(the
base interval.)
5. The time the Scheduler 'notifies' a waiting Queue Thread.
The maximum time allowable is 2(bi)
(two times
the base interval.)
For 1-5 [ Is all this necessary? ]
When the Thread exceeds the time, the Monitor sets the
entry 'cancelled'. The next time the Monitor runs, it sets all 'cancelled'
entries 'disabled'. If a Thread resumes processing, the Thread resets the entry,
irrespective of any prior setting. Each time the Thread changes status it resets the
time. Therefore, this is not a cumulative total nor overall elapsed time.
As stated above, disabled Threads cannot participate in scheduling.
However, users may enable those disabled Threads with the
Queue Threads GUI/non-GUI. Now it gets
interesting.
"Enabling all threads" nulls the instance reference to the actual Thread
in the Thread-Management Class (AreaThreadMgmt) and sets the status
of the Thread in the same class to "available for a new thread". If the old
Thread awakens, it both checks to see if it's instance reference is null
or if another thread has taken its place and dies gracefully. For a more detailed discussion of
expunged threads, see the AreaThreadMgmt Class and
the footnote.

These next two timed events do not involve setting the status to 'disabled'. We mention
them here since they are part of the seven timed events.
6. The time the Thread begins 'waiting for work'.
The maximum time allowable is the Wait Time interval for the Thread as set in Queue
Maintenance (TyQueMaint).
For 6, each Thread sets its own entry 'inactive', not the
Monitor. A Queue Threshold exception must take place to reactivate this
thread. For a discussion of this event, see the section on Tuning.
7. The time the Thread enters a status of 'inactive' (6,
above) and the Queue is participating in the Idle Thread
Life parameter.
For 7, The maximum time allowable is the Idle Thread Life interval for
the Thread as set in Queue Maintenance (TyQueMaint). When
the Thread exceeds the time, the Monitor destroys the Thread. Tymeac must get a new
instance of the Thread and start() it when necessary.
The interval of
the timed events (1-5) is as above. Using variables for
System (and Queue) would establish an exclusive environment for a particular need. When the requirements change, the variables would need
changing. When the platform changes, the variables would need changing. Each
application on each platform would need re-engineering each time the need changes
either internally by function or externally by porting.
Tymeac event timing functions identically on all platforms. Adjusting the Monitor
Thread interval sets the interval across all Tymeac timed events. Porting to any machine
preserves the same application demeanor (synergy) it acts the same only faster (or
slower).
See also:
Tuning, (Wait Lists, fixed number
of entries within each Queue).
Stall Array for timing of Asynchronous
Requests.
Monitor for timing of Synchronous Requests.
In order to know if all this timing is necessary we must first answer the
question, "Can a thread stall or die during processing?"
The answer is yes.
Hardware, operating systems, the implementation of the JVM, Tymeac code and user
code can all fail at anytime. Tymeac is a professional product; professionals
plan for anomalies. Now, on to the timing question.
It should be obvious that when Tymeac invokes your Processing Application
Class, the execution may block or take an excessive amount of time. It may even
stall completely. Therefore, timing this event is a no-brainer. That takes care
of number 3.
Numbers 5 and sometimes 1 have to do with Thread state changes. That is,
going from a waiting or timed waiting state to a running state. (See
java.lang.Thread state codes.) It is unlikely that there would be a significant
delay in the thread getting CPU time after this state change, but it could
happen.
Numbers 4 and sometimes 1 have to do with creating a new thread either for
the Normal or Output Agent Queue. Since creating a new thread usually involves
communicating with the underlying operating system, there could be a delay. It
is unlikely that there would be a significant delay, but it could happen.
Number 2 is Tymeac code. As much as
we like to think it is unlikely that there could be a bug, it could happen.
Finally there is just plain something going wrong somewhere. Like the "spurious
wakeup" that may happen to a waiting thread, a running thread may also die
or stall or another thread may damage the current thread's control structure at
the operating system level. It could happen.
The consistent phrase here is "it could happen." What we really mean is it
could happen again. Having done multi-tasking/threading for many decades we've run
into these problems before and we expect to see them again.
Therefore, all this timing is necessary. But what about all the overhead?
There isn't much overhead associated with
this timing.
- Each time a Queue Thread changes status it checks whether it
has been expunged. If not, it sets the current time (System.currentTimeMillis())
into the field associated with this current status and nulls the time fields
associated with other status codes. This is very little work and no object
creation.
- For a heavily used system the status changes are from Tymeac code to the
Application code and back to Tymeac code. This is: fetching a request from the
wait list, the application process, saving the application's object and
fetching the next request. Exactly where timing is most necessary (the
no-brainer above.)
- When the Tymeac Monitor runs (probably about once a minute) it checks only
one timing event: the current status of the Queue Thread. This is very little
work and also no object creation.
For all the benefits of timing, the overhead is piddle.