Вы объединяете два разных done()
метода. Один из SwingWorker
, который вы собираетесь переопределить. Ничего особенного с Runnable
не должно произойти в вашей реализации done()
, только ваш собственный код. (Надежная реализация done()
проверит на isCancelled
, возможно, вызовет get()
, если вы не вызываете его в другом месте, и обработает все исключения, которые могли быть выданы работником, и т. Д. c. Но вы не Чтобы сделать что-нибудь из этого, нужно обернуть Runnable
.)
Другой метод - FutureTask
. Это сбивает с толку, потому что SwingWorker сам использует FutureTask для выполнения «реальной» работы по параллелизму. FutureTask#done()
- это , также , предназначенный для переопределения клиентами, но в этом случае клиентом является SwingWorker, а не вы.
Когда вы вызываете execute (), SwingWorker's future
( частная переменная экземпляра FutureTask) запускается, и вот что происходит:
future.run()
выполняется в рабочем потоке.
future.run()
вызывает Callable, переданный, как вы цитировали выше, изменяя состояние на STARTED (которое отправляет событие свойства) и вызывая doInBackground
. Ваш собственный рабочий код запускается и возвращает результат.
future.run()
вызывает собственный метод 'set' для сохранения результата и пометки вычисления как завершенного. Он также вызывает закрытый метод finishCompletion
.
future.finishCompletion()
, который пробуждает любые другие потоки, которые вызвали SwingWorker's get()
(и поэтому были заблокированы все это время). Эти вызовы get()
могут возвращать результат вычисления своим абонентам одновременно с остальной частью этого списка.
future.finishCompletion()
вызывает свой собственный done()
. Обычно это пустой метод, но, как вы цитировали выше, SwingWorker сделал переопределение. Так что этот конкретный FutureTask done()
делает еще две вещи: во-первых, он вызывает SwingWorker#doneEDT()
, который просто вызывает SwingWorker#done()
в потоке диспетчеризации событий. Это версия done()
, которую вы переопределяете в своем подклассе SwingWorker. А во-вторых, он изменяет состояние на DONE, которое отправляет другое событие изменения свойства.
future
s finishCompletion()
возвращается к своему методу set, который возвращает к run()
, который занимается уборкой и возвращается. В этот момент рабочий поток освобождается для других целей (новые рабочие места, сон, хобби и т. Д.).
Ваше участие будет только в SwingWorker's done()
, если вы хотел подкласс это. Благодаря манипулированию SwingWorker, ваше собственное переопределение done()
гарантированно будет выполнено в потоке диспетчеризации событий, так что вы можете безопасно работать с визуальными компонентами Swing. Имейте в виду, что done()
также вызывается в случае отмены SwingWorker, даже если cancel()
был вызван до execute()
- фактически, done()
вызывается до того, как cancel()
возвращается - так что проверьте соответствующий статус внутри вашего переопределить.