What design pattern is best for updating the GUI when dealing with other threads in Java (Swing)?
For example, imagine an Object (like a custom JPanel) that has a JList that has a DefaultListModel supporting it. A threading listening on a Socket can receive data and then wants to update the JList from the information that came in on the socket.
I understand the SwingUtilities.invokeLater, but that seems like sloopy code, because in reality I have many different functions that can be called (from non EDT threads) that manipulate different GUI components.
The idea that I thought of is creating some kind of messaging system with an ArrayBlockingQueue. Basically I implement Runnable and in the SwingUtilities.invokeLater method call I pass in this. Then the method gets executed, but it doesn't really know what to do, but that is where I pop the "messages" from the thread safe ArrayBlockingQueue.
Is there a better design pattern than this? My base JPanel Class
public class JPanelGUIThread extends JPanel implements Runnable
{
    protected ArrayBlockingQueue<Object> guiUpdateMessages;
    
    public JPanelGUIThread()
    {
        guiUpdateMessages = new ArrayBlockingQueue<Object>(10);
    }
    
    @Override
    public void run()
    {
        while(guiUpdateMessages.size() > 0)
        {
            try
            {
                Object data = guiUpdateMessages.take();
                
                if(data instanceof Object[])
                {
                    handleGUIUpdateArray((Object[])data);
                }
                else
                {
                    handleGUIUpdateObject(data);
                }
                
            } 
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }
    
    public void handleGUIUpdateArray(Object[] objectArray)
    {
        
    }
    public void handleGUIUpdateObject(Object object)
    {
        
    }
}
My main JPanel
    
    public JLabel getChatLabel()
    {
        return chatLabel;
    }
    public JTextArea getChatArea()
    {
        return chatArea;
    }
    public JScrollPane getChatScrollPane()
    {
        return chatScrollPane;
    }
    public JTextField getMychat()
    {
        return mychat;
    }
    public JButton getSendButton()
    {
        return sendButton;
    }
    //This method is called from the EDT, so no need to perform adding messages
    @Override
    public void actionPerformed(ActionEvent e)
    {
        if(e.getSource() == sendButton)
        {
            client.sendChatInformation(mychat.getText());
            mychat.setText("");
        }
    }
    public void clearOldChat()
    {
        Object[] data = new Object[3];
        data[0] = chatArea;
        data[1] = MessageType.SET;
        data[2] = "";
        guiUpdateMessages.add(data);
        SwingUtilities.invokeLater(this);
    }
    @Override
    public void handleGUIUpdateArray(Object[] objectArray)
    {
        if(objectArray[0] == chatArea)
        {
            if(objectArray[1] == MessageType.APPEND)
            {
                chatArea.append((String) objectArray[2]);
            }
            else if(objectArray[1] == MessageType.SET)
            {
                chatArea.setText((String) objectArray[2]);
            }
            
        }
    }
}