Metoda process(List<V>) jest wywoływana w EDT, więc tam nie musisz nic synchronizować. Zachowanie jest zgodne z oczekiwanym, gdyż wyniki metody publish są łączone w listę, jeżeli EDT jest zajęty i nie można wywołać process od razu.
W twoim przypadku chyba jednak dobrze by było zmienić podejście. Do głowy przyszedł mi następujący pomysł:
- Utworzyć normalne Thready, które generują litery.
- W środku tych Threadów tworzyć nowe Runnable dla każdej litery i wywoływać SwingUtilites.invokeLater() na nich.
Rozwiązanie to ma jednak pewną zasadniczą wadę. Jeżeli skolejkujesz za dużo zadań to interfejs się zawiesi. Nowe eventy lądują chyba na końcu listy, więc dowolny event, np kliknięcie, będzie musiał poczekać, aż wykonają się wszystkie zadania, które były w kolejce, gdy był do niej dodawany.
EDIT:
W sumie można skorzystać też z invokeAndWait() i wtedy raczej nie zaspamujemy tak bardzo kolejki do EDT.