Foxtrot API
The Foxtrot API is very small and simple, and consists of 3 main classes:
class foxtrot.Worker
class foxtrot.Task
class foxtrot.Job
From Foxtrot 2.x, the API has been extended to allow customization of the part that handles event pumping
and of the part that handles execution of Task s and Job s in a worker thread, via
the following classes:
interface foxtrot.EventPump
interface foxtrot.WorkerThread
class foxtrot.AbstractWorkerThread
Normally users do not need to deal with these classes to use Foxtrot in their Swing applications, since
Foxtrot will configure itself with the most suitable implementations; however, if
a specific customization of the event pumping mechanism or of the worker thread mechanism is needed, the APIs
provided by these classes allow fine grained control on Foxtrot's behavior.
Foxtrot API Details
The Worker class is used to post Task s or Job s that will be executed
in the Foxtrot Worker Thread.
The Task class is subclassed by the user to perform heavy tasks that throw checked exceptions.
The Job class, conversely, is subclassed by the user to perform heavy tasks that do not throw
checked exceptions, but only RuntimeExceptions (or Errors).
The Worker class has the following 2 public methods that can be used to post
Task s or Job s:
public static Object post(Task task) throws Exception
public static Object post(Job job)
The Task class has a single abstract method that must be implemented by the user, with the
time-consuming code that may throw checked exceptions:
public abstract Object run() throws Exception
The Job class, conversely, has a single abstract method that must be implemented by the user,
with the time-consuming code that does not throw checked exceptions:
public abstract Object run()
The exceptions or errors thrown inside the Task.run() or Job.run() methods are
re-thrown by the corrispondent Worker.post(...) method as is, i.e. without being wrapped into,
for example, an InvocationTargetException.
The usage is very simple; here's an example with the Job class:
Worker.post(new Job()
{
public Object run()
{
// Here write the time-consuming code
// that does not throw checked exceptions
}
});
and here's an example with the Task class:
try
{
Worker.post(new Task()
{
public Object run() throws Exception
{
// Here write the time-consuming code
// that may throw checked exceptions
}
});
}
catch (Exception x)
{
// Handle the exception thrown by the Task
}
It is possible to narrow the throws clause of the Task class, but unfortunately not the one of
the Worker class.
So, when using the Worker.post(Task task) method, you have to surround it in a
try...catch(Exception x) block (unless the method that contains Worker.post(Task task)
throws Exception itself).
try
{
Worker.post(new Task()
{
public Object run() throws FileNotFoundException
{
// Here write the time-consuming code
// that accesses the file system
}
});
}
catch (FileNotFoundException x)
{
// Handle the exception or rethrow.
}
catch (RuntimeException x)
{
// RuntimeExceptions are always possible.
// Catch them here to prevent they are
// ignored by the catch(Exception ignored)
// block below.
throw x;
}
catch (Exception ignored)
{
// No other checked exceptions are thrown
// by the Task (the compiler will enforce this),
// so we can safely ignore it, but we're forced
// to write this catch block: Worker.post(Task t)
// requires it.
}
The Worker class, from Foxtrot 2.x, has the following public methods to deal with the
EventPump and WorkerThread components:
public static EventPump getEventPump()
public static void setEventPump(EventPump pump)
public static WorkerThread getWorkerThread()
public static void setWorkerThread(WorkerThread worker)
Foxtrot configures itself automatically with the most suitable implementation of
EventPump and WorkerThread .
Some implementations of EventPump or WorkerThread allow an even further customization
of the component.
For example, implementations of EventPump that also implement the
foxtrot.pumps.EventFilterable interface may allow the user to filter events that are being dispatched
by the java.awt.EventQueue . See also the bundled Javadocs for further details.
However, it is recommended not to exploit these features unless knowing exactly what one is doing:
Foxtrot's defaults may change from version to version to suit better implementations, and these defaults may depend
on the Java Runtime Environment version Foxtrot is running on, so that features working in JDK 1.3.x may not work
in JDK 1.4.x or viceversa.
Playing with AWT events too badly is normally looking for troubles, so consider you warned :)
The same holds for WorkerThread implementations, that should extend the abstract class
AbstractWorkerThread : Foxtrot uses a synchronous model, so replacing (for example)
the default WorkerThread implementation (that uses a single worker thread) with an implementation
that uses multiple pooled threads does not lead (in the common case) to a great speed-up of Task s
execution.
To be more precise, with a multiple thread implementation of WorkerThread , Tasks posted
from pumped events will return control to the initial caller after a time that is (roughly) the time of the
longest Task , while with the default implementation will be after a time that is (roughly) the sum
of the times of all Task s posted from pumped events.
Task s posted from pumped events are normally a rare case, and may not be worth the effort of
a multiple thread implementation of WorkerThread .
Refer to the bundled Javadoc documentation for further information, and to the bundled examples for
further details on how to use the Foxtrot classes with Swing. And do not forget the
Tip 'n' Tricks section !
|