public final class RequestProcessor extends Object implements ScheduledExecutorService
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 = newThe above example guarantees that there is at most one runnable being processed in parallel. All your requests are serialized and processed one by one.RequestProcessor(MyClass.class)
; // later RP.post(runnable, delay)
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.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 waitFinished()
:
private static final RequestProcessor RP = new RequestProcessor("My tasks"); private volatileRequestProcessor.Task
last; // when posting update the task last = RP.post(runnable, delay)
// later wait last.waitFinished()
Periodic task
It is also possible to do something periodically. Use the schedule
method:
class Periodic implements Runnable { private static final RequestProcessor RP = newPlease 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.RequestProcessor(Periodic.class)
; private final RequestProcessor.Task CLEANER = RP.create(this)
; public void run() { doTheWork(); CLEANER.schedule(DELAY); } }
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 = newThe above code coalesces all events that arrive in 1s and for all of them doesRequestProcessor(Updater.class)
; private final RequestProcessor.Task UPDATE = RP.create(this)
; public void propertyChange(PropertyChangeEvent ev) { UPDATE.schedule(1000)
; } public void run() { doTheWork(); } }
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.cancel()
but 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("Interruptible", 1, true)
;
public void run () {
while (veryLongTimeLoop) {
doAPieceOfIt ();
if (Thread.interrupted ()) return;
}
}
Since org.openide.util
, implements
ScheduledExecutorService
Modifier and Type | Class and Description |
---|---|
class |
RequestProcessor.Task
The task describing the request sent to the processor.
|
Constructor and Description |
---|
RequestProcessor()
Creates new RequestProcessor with automatically assigned unique name.
|
RequestProcessor(Class<?> forClass)
Convenience constructor for a new RequestProcessor with throughput 1.
|
RequestProcessor(String name)
Creates a new named RequestProcessor with throughput 1.
|
RequestProcessor(String name,
int throughput)
Creates a new named RequestProcessor with defined throughput.
|
RequestProcessor(String name,
int throughput,
boolean interruptThread)
Creates a new named RequestProcessor with defined throughput which
can support interruption of the thread the processor runs in.
|
RequestProcessor(String name,
int throughput,
boolean interruptThread,
boolean enableStackTraces)
Creates a new named
RequestProcessor that allows to disable stack trace filling. |
Modifier and Type | Method and Description |
---|---|
boolean |
awaitTermination(long timeout,
TimeUnit unit) |
RequestProcessor.Task |
create(Runnable run)
Creates request that can be later started by setting its delay.
|
RequestProcessor.Task |
create(Runnable run,
boolean initiallyFinished)
Creates request that can be later started by setting its delay.
|
static RequestProcessor.Task |
createRequest(Runnable run)
Deprecated.
Sharing of one singlethreaded
RequestProcessor
among different users and posting even blocking requests is inherently
deadlock-prone. See use cases . |
void |
execute(Runnable command)
Implements contract of
Executor . |
static RequestProcessor |
getDefault()
Warning: The instance of
RequestProcessor returned
by this method has very bad performance side effects, don't use unless
you understand all implications! |
<T> List<Future<T>> |
invokeAll(Collection<? extends Callable<T>> tasks) |
<T> List<Future<T>> |
invokeAll(Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit) |
<T> T |
invokeAny(Collection<? extends Callable<T>> tasks) |
<T> T |
invokeAny(Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit) |
boolean |
isRequestProcessorThread()
Tests if the current thread is request processor thread.
|
boolean |
isShutdown() |
boolean |
isTerminated() |
RequestProcessor.Task |
post(Runnable run)
This methods asks the request processor to start given
runnable immediately.
|
RequestProcessor.Task |
post(Runnable run,
int timeToWait)
This methods asks the request processor to start given
runnable after
timeToWait milliseconds. |
RequestProcessor.Task |
post(Runnable run,
int timeToWait,
int priority)
This methods asks the request processor to start given
runnable after
timeToWait milliseconds. |
static RequestProcessor.Task |
postRequest(Runnable run)
Deprecated.
Sharing of one singlethreaded
RequestProcessor
among different users and posting even blocking requests is inherently
deadlock-prone. See use cases . |
static RequestProcessor.Task |
postRequest(Runnable run,
int timeToWait)
Deprecated.
Sharing of one singlethreaded
RequestProcessor
among different users and posting even blocking requests is inherently
deadlock-prone. See use cases . |
static RequestProcessor.Task |
postRequest(Runnable run,
int timeToWait,
int priority)
Deprecated.
Sharing of one singlethreaded
RequestProcessor
among different users and posting even blocking requests is inherently
deadlock-prone. See use cases . |
<T> ScheduledFuture<T> |
schedule(Callable<T> callable,
long delay,
TimeUnit unit) |
ScheduledFuture<?> |
schedule(Runnable command,
long delay,
TimeUnit unit) |
ScheduledFuture<?> |
scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit) |
ScheduledFuture<?> |
scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit) |
void |
shutdown() |
List<Runnable> |
shutdownNow() |
void |
stop()
Stops processing of runnables processor.
|
<T> Future<T> |
submit(Callable<T> task) |
Future<?> |
submit(Runnable task) |
<T> Future<T> |
submit(Runnable task,
T predefinedResult)
Note: If the passed
Runnable implements
Cancellable , then that object's Cancellable.cancel()
method will be called if Future.cancel(boolean) is invoked. |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
close
public RequestProcessor()
public RequestProcessor(String name)
name
- the name to use for the request processor threadpublic RequestProcessor(Class<?> forClass)
class MyClass { private static final RequestProcessor RP = new RequestProcessor(MyClass.class); }Behaves as
new RequestProcessor(MyClass.class.getName())
.forClass
- name of this class gives name for the processor threadspublic RequestProcessor(String name, int throughput)
name
- the name to use for the request processor threadthroughput
- the maximal count of requests allowed to run in parallelpublic RequestProcessor(String name, int throughput, boolean interruptThread)
RequestProcessor.Task.cancel()
but if the task was already running, one was out of luck. With this
constructor one can create a RequestProcessor
which threads
thread running tasks are 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 immediatelly as in this example:
public void run () { while (veryLongTimeLook) { doAPieceOfIt (); if (Thread.interrupted ()) return; } }
name
- the name to use for the request processor threadthroughput
- the maximal count of requests allowed to run in parallelinterruptThread
- true if RequestProcessor.Task.cancel()
shall interrupt the threadpublic RequestProcessor(String name, int throughput, boolean interruptThread, boolean enableStackTraces)
RequestProcessor
that allows to disable stack trace filling.
By default, when assertions are on, each task posted on RequestProcessor
stores
the stack trace at the time of posting. When an exception is later thrown from the task,
it allows to print not only stack trace of the task but also stack trace of the code that posted it.
However this may be a performance bottleneck in cases when hundreds of short task are scheduled.
This constructor then allows to create RequestProcessor
which never stores stack traces
at the time of posting.
See constructor RequestProcessor.RequestProcessor(String, int, boolean)
for details of interruptThread
parameter.
name
- the name to use for the request processor threadthroughput
- the maximal count of requests allowed to run in parallelinterruptThread
- true if RequestProcessor.Task.cancel()
shall interrupt the threadenableStackTraces
- false
when request processor should not fill stack traces when task is posted.
Default is true
when assertions are enabled, false
otherwise.public static RequestProcessor getDefault()
RequestProcessor
returned
by this method has very bad performance side effects, don't use unless
you understand all implications!
This is the getter for the shared instance of the RequestProcessor
.
This instance is shared by anybody who
needs a way of performing sporadic asynchronous work.
The problem of this method lays exactly in the definition of sporadic.
Often one needs to process something at some sporadic moment,
but, for example
due to storm of events, one needs to execute more than one tasks
at the same sporadic moment. In this situation
using RequestProcessor.getDefault()
is horribly inefficient. All such tasks
would be processed in parallel, allocating their own execution threads
(up to 50). As the price per one thread is estimated to 1MB on common
systems, you shall think twice whether you want to increase the memory
consumption of your application so much at these sporadic moments.
There is a runtime detection of the parallel misuse of this method since version 8.3. It is activated only in development mode (when executed with assertions on) and prints warning into log whenever there are more than three same tasks running in parallel. In case you see such warning, or in case you are in doubts consider creation of your own, private, single throughput processor:
class YourClass {
private static final RequestProcessor RP = new RequestProcessor(YourClass.class)
;
}
Such private field is lightweight and guarantees that all your tasks
will be processed sequentially, one by one. Just don't forget to make
the field static!
Tasks posted to this instance may be canceled until they start their
execution. If a there is a need to cancel a task while it is running
a seperate request processor needs to be created via
RequestProcessor.RequestProcessor(String, int, boolean)
constructor.
RequestProcessor.RequestProcessor(String, int, boolean)
,
RequestProcessor.Task.cancel()
public void execute(Runnable command)
Executor
.
Simply delegates to RequestProcessor.post(java.lang.Runnable)
.public RequestProcessor.Task post(Runnable run)
Thread.MIN_PRIORITY
.run
- class to runpublic RequestProcessor.Task post(Runnable run, int timeToWait)
timeToWait
milliseconds. The default priority is Thread.MIN_PRIORITY
.run
- class to runtimeToWait
- to wait before executionpublic RequestProcessor.Task post(Runnable run, int timeToWait, int priority)
timeToWait
milliseconds. Given priority is assigned to the
request. For request relaying please consider:
post(run, timeToWait, Thread.currentThread().getPriority());
run
- class to runtimeToWait
- to wait before executionpriority
- the priority from Thread.MIN_PRIORITY
to Thread.MAX_PRIORITY
public RequestProcessor.Task create(Runnable run)
!isFinished()
so doing waitFinished() will
block on and wait until the task is scheduled.run
- action to run in the processpublic RequestProcessor.Task create(Runnable run, boolean initiallyFinished)
run
- action to run in the processinitiallyFinished
- should the task be marked initially finished? If
so the RequestProcessor.Task.waitFinished()
on the task will succeeded immediatelly even
the task has not yet been RequestProcessor.Task.schedule(int)
d.public boolean isRequestProcessorThread()
waitFinished
method. Any two tasks created
by request processor must not wait for themself.true
if the current thread is request processor
thread, otherwise false
public void stop()
@Deprecated public static RequestProcessor.Task postRequest(Runnable run)
RequestProcessor
among different users and posting even blocking requests is inherently
deadlock-prone. See use cases
.timeToWait
milliseconds. The default priority is Thread.MIN_PRIORITY
.run
- class to run@Deprecated public static RequestProcessor.Task postRequest(Runnable run, int timeToWait)
RequestProcessor
among different users and posting even blocking requests is inherently
deadlock-prone. See use cases
.timeToWait
milliseconds.
The default priority is Thread.MIN_PRIORITY
.run
- class to runtimeToWait
- to wait before execution@Deprecated public static RequestProcessor.Task postRequest(Runnable run, int timeToWait, int priority)
RequestProcessor
among different users and posting even blocking requests is inherently
deadlock-prone. See use cases
.timeToWait
milliseconds. Given priority is assigned to the
request.run
- class to runtimeToWait
- to wait before executionpriority
- the priority from Thread.MIN_PRIORITY
to Thread.MAX_PRIORITY
@Deprecated public static RequestProcessor.Task createRequest(Runnable run)
RequestProcessor
among different users and posting even blocking requests is inherently
deadlock-prone. See use cases
.run
- action to run in the processpublic void shutdown()
shutdown
in interface ExecutorService
IllegalStateException
- if called on the
default request processorpublic List<Runnable> shutdownNow()
shutdownNow
in interface ExecutorService
IllegalStateException
- if called on the
default request processorpublic boolean isShutdown()
isShutdown
in interface ExecutorService
public boolean isTerminated()
isTerminated
in interface ExecutorService
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
awaitTermination
in interface ExecutorService
InterruptedException
public <T> Future<T> submit(Callable<T> task)
Note: If the passed Callable
implements
Cancellable
, then that object's Cancellable.cancel()
method will be called if Future.cancel(boolean)
is invoked.
If Cancellable.cancel()
returns false, then the job will not be
cancelled.
submit
in interface ExecutorService
public <T> Future<T> submit(Runnable task, T predefinedResult)
Runnable
implements
Cancellable
, then that object's Cancellable.cancel()
method will be called if Future.cancel(boolean)
is invoked.
If Cancellable.cancel()
returns false, then the job will not be
cancelled.submit
in interface ExecutorService
public Future<?> submit(Runnable task)
Note: If the passed Runnable
implements
Cancellable
, then that object's Cancellable.cancel()
method will be called if Future.cancel(boolean)
is invoked.
If Cancellable.cancel()
returns false, then the job will not be
cancelled.
submit
in interface ExecutorService
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException
invokeAll
in interface ExecutorService
InterruptedException
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException
Executes the given tasks, returning a list of Futures holding their status and results when all complete or the timeout expires, whichever happens first.
invokeAll
in interface ExecutorService
InterruptedException
public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException
Executes the given tasks, returning the result of one which has completed and cancelling any incomplete tasks.
invokeAny
in interface ExecutorService
InterruptedException
ExecutionException
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
Executes the given tasks, returning a list of Futures holding their status and results when all complete or the timeout expires, whichever happens first.
invokeAny
in interface ExecutorService
T
- The result typetasks
- A collection of callablestimeout
- The maximum time to wait for completion, in the specified time unitsunit
- The time unitInterruptedException
- if the timeout expires or execution is interruptedExecutionException
TimeoutException
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
schedule
in interface ScheduledExecutorService
public <T> ScheduledFuture<T> schedule(Callable<T> callable, long delay, TimeUnit unit)
schedule
in interface ScheduledExecutorService
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
Schedules a runnable which will run with a given frequency, regardless of how long execution takes, with the exception that if execution takes longer than the specified delay, execution will be delayed but will never be run on two threads concurrently.
scheduleAtFixedRate
in interface ScheduledExecutorService
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
Schedules a runnable which will run repeatedly after the specified initial delay, with the specified delay between the completion of one run and the start of the next.
scheduleWithFixedDelay
in interface ScheduledExecutorService