How can I operation occasionally on a background thread, but reschedule it if something happens to delay it?
There are a lot of reasons you might want to reschedule a background operation. For example, you want to re-parse a file 3 seconds after the user stops typing, so you can show errors. But at 2 seconds she starts typing again. You don’t want that task to run a second from now anymore. You can either cancel the task, or even simpler, call task.schedule(3000)
every time a key is pressed. If it was already scheduled, it will be rescheduled for 3 seconds from now again.
Or imagine you have the situation described in the FAQ about RequestProcessor.getDefault() - a node for a file needs to read the file after it is created to mark itself if the file has errors. RequestProcessor.Task
makes this sort of thing easy.
public class FooDataNode extends DataNode implements PropertyChangeListener, Runnable {
private boolean error;
private static final RequestProcessor THREAD_POOL = new RequestProcessor("FooDataNode processor", 1);
private final RequestProcessor.Task task = THREAD_POOL.create(this);
FooDataNode(FooDataObject obj) {
super(obj, Children.LEAF);
obj.addPropertyChangeListener(WeakListeners.propertyChange(this, obj));
task.schedule(100);
}
public void propertyChange(PropertyChangeEvent evt) {
DataObject obj = (DataObject) evt.getSource();
if (DataObject.PROP_MODIFIED.equals(evt.getPropertyName()) && !obj.isModified()) { //file was saved
task.schedule(100);
}
}
@Override
public String getHtmlDisplayName() {
return error ? "<font color=\"!nb.errorForeground\">" + getDisplayName() : null;
}
public void run() {
boolean old = error;
error = doesTheFileHaveErrors();
if (old != error) {
fireDisplayNameChange(null, null);
}
}
private boolean doesTheFileHaveErrors() {
assert !EventQueue.isDispatchThread();
//parse the file here
return true; //whatever the value should be
}
}