Request processor is
Executor (since version 7.16) capable to
perform asynchronous requests in a dedicated thread pool.
There are several use cases for RequestProcessor,
most of them start with creating own
RequestProcessor
instance (which by itself is quite lightweight).
Do something later
In case you want something to be done later in some background thread,
create an instance of
RequestProcessor
and post tasks to it.
private static final RequestProcessor RP = new
RequestProcessor#RequestProcessor(java.lang.Class);
// later
RP.
#post(java.lang.Runnable,int)
The above example guarantees that there is at most one runnable being
processed in parallel. All your requests are serialized and processed
one by one.
RP
works here like a simple mutex.
In case you want more tasks to run in parallel (not very often use case)
you can specify higher
throughput via
#RequestProcessor(java.lang.String,int). Then
the RP
works like a queue of requests passing through a
semaphore with predefined number of DOWN()
s.
You can wait for your tasks to be processed by keeping a reference to the
last one and using
RequestProcessor.Task#waitFinished:
private static final RequestProcessor RP = new RequestProcessor("My tasks");
private volatile
RequestProcessor.Task last;
// when posting update the task
last = RP.
#post(java.lang.Runnable,int)// later wait
last.
RequestProcessor.Task#waitFinished
Periodic task
It is also possible to do something periodically. Use the
RequestProcessor.Task#schedule method:
class Periodic implements Runnable {
private static final RequestProcessor RP = new
RequestProcessor#RequestProcessor(java.lang.Class);
private final RequestProcessor.Task CLEANER = RP.
#create(java.lang.Runnable);
public void run() {
doTheWork();
CLEANER.schedule(DELAY);
}
}
Please think twice before using such periodic
background activity. It is generally considered evil if some code runs
without any user action. Your code shall respect the application's state,
and for example when the application is minimized, do nothing.
Sliding task
Often you want to perform an update of your object internals
based on changes in some model. However your update may be costly
and you want to do it just once, regardless of how many changes are
reported by the model. This can be achieved with a sliding task:
class Updater implements PropertyChangeListener, Runnable {
private static final RequestProcessor RP = new
RequestProcessor#RequestProcessor(java.lang.Class);
private final RequestProcessor.Task UPDATE = RP.
#create(java.lang.Runnable);
public void propertyChange(PropertyChangeEvent ev) {
UPDATE.
RequestProcessor.Task#schedule;
}
public void run() {
doTheWork();
}
}
The above code coalesces all events that arrive in 1s and for all of them
does
doTheWork
just once.
Interruption of tasks
Since version 6.3 there is a conditional support for interruption of long running tasks.
There always was a way to cancel not yet running task using
RequestProcessor.Task#cancelbut if the task's run() method was already running, one was out of luck.
Since version 6.3
the thread running the task is interrupted and the Runnable can check for that
and terminate its execution sooner. In the runnable one shall check for
thread interruption (done from
RequestProcessor.Task#cancel) and
if true, return immediately as in this example:
private static final RequestProcessor RP = new
#RequestProcessor(String,int,boolean);
public void run () {
while (veryLongTimeLoop) {
doAPieceOfIt ();
if (Thread.interrupted ()) return;
}
}
Since org.openide.util
, implements
java.util.concurrent.ScheduledExecutorService