Вы все правильно делаете. GUI в подавляющем большинстве случаев выносится в один поток. Кроме этого используется еще произвольное количество потоков для бэкграунд тасков, приема пакетов (в т.ч. tcp), отправки запросов и т.д.
Навскидку — после получения каждого пакета дергаются листенеры, которые и обновляют UI.
Будет время — поищу что-нибудь конкретное.