В рамках изучения SwingWorker я изучал исходный код, где заметил нечто, называемое AccumulativeRunnable. Из комментария к определению класса AccumulativeRunnable я понимаю, когда его следует использовать, но когда я проверял код примера, у меня возникли несколько вопросов.
Ниже приведен комментарий и пример кода в абстрактном классе AccumulativeRunnable.
Абстрактный класс (AccumulativeRunnable) для использования в тех случаях, когда нам нужно выполнить некоторые действия над добавляемым набором данных.
Набор данных может быть добавлен после того, как он отправлен для выполнение. Обычно такие Runnables отправляются в EDT.
Пример использования: Скажем, мы хотим реализовать JLabel.setText (текст String), который отправляет строку в JLabel.setTextImpl (текст String) на ПО ВОСТОЧНОМУ ВРЕМЕНИ. В случае, если JLabel.setText быстро вызывается много раз с EDT, мы получим много обновлений на EDT, но важен только последний. (Каждое следующее обновление отменяет предыдущее.) Мы можем захотеть реализовать это таким образом, чтобы доставлялось только последнее обновление.
AccumulativeRunnable<String> doSetTextImpl =
new AccumulativeRunnable<String>()} {
protected void run(List<String> args)} {
//set to the last string being passed
setTextImpl(args.get(args.size() - 1));
}
}
void setText(String text) {
//add text and send for the execution if needed.
doSetTextImpl.add(text);
}
Вопросы
- абстрактный класс AccumulativeRunnable
implements
Runnable
. Это означает, что класс AccumulativeRunnable должен реализовывать метод run, верно? Но я мог видеть только protected abstract void
run(List<T> args);
. Как это может быть реализацией интерфейса Runnable
. - Почему метод
add()
класса AccumulativeRunnable равен synchronized
? Может кто-нибудь объяснить это на простом примере или на примере, который я привел выше. - Когда
arguments
внутри add()
метода класса AccumulativeRunnable будет null
? Может кто-нибудь объяснить это на простом примере или на примере, который я привел выше. - Как метод
add()
получает массив (T ... args)? Может ли кто-нибудь объяснить это на простом примере или на примере, который я привел выше. - В приведенном выше примере, когда мы вызываем
doSetTextImpl.add(text);
, он вызывает метод add()
класса AccumulativeRunnable. Но как это внутренне вызывать метод run()
? Я имею в виду, кто вызывает наш реализованный метод run()
внутри.
Весь код в AccumulativeRunnable:
public abstract class AccumulativeRunnable<T> implements Runnable {
private List<T> arguments = null;
/**
* Equivalent to {@code Runnable.run} method with the
* accumulated arguments to process.
*
* @param args accumulated argumets to process.
*/
protected abstract void run(List<T> args);
/**
* {@inheritDoc}
*
* <p>
* This implementation calls {@code run(List<T> args)} mehtod
* with the list of accumulated arguments.
*/
public final void run() {
run(flush());
}
/**
* appends arguments and sends this {@code Runnable} for the
* execution if needed.
* <p>
* This implementation uses {@see #submit} to send this
* {@code Runnable} for execution.
* @param args the arguments to accumulate
*/
@SafeVarargs
@SuppressWarnings("varargs") // Copying args is safe
public final synchronized void add(T... args) {
boolean isSubmitted = true;
if (arguments == null) {
isSubmitted = false;
arguments = new ArrayList<T>();
}
Collections.addAll(arguments, args);
if (!isSubmitted) {
submit();
}
}
/**
* Sends this {@code Runnable} for the execution
*
* <p>
* This method is to be executed only from {@code add} method.
*
* <p>
* This implementation uses {@code SwingWorker.invokeLater}.
*/
protected void submit() {
SwingUtilities.invokeLater(this);
}
/**
* Returns accumulated arguments and flashes the arguments storage.
*
* @return accumulated arguments
*/
private synchronized List<T> flush() {
List<T> list = arguments;
arguments = null;
return list;
}
}