I'm using multi threading with Java, I have a thread that will post a message into a queue, a blockingQueue which is thread safe, and I have another thread, implementing a GUI with swing. Everytime I'm checking whether the queue is empty or not, if not, I poll the message and add it to DefaultListModel, but the problem the display is not updated. I made sure that the message polled is not empty. This is the code: For the implementation of the JList
historyListModel = new DefaultListModel<String>();
historyList = new JList<String>(historyListModel);
historyList.setAutoscrolls(true);
JScrollPane historyScroll = new JScrollPane(historyList);
add(historyScroll, BorderLayout.CENTER);
Adding message to the queue
private BlockingQueue<String> messageRes = new LinkedBlockingQueue<>();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String msgReceived = new String(packet.getData(), 0, packet.getLength());
messageRes.add(msgReceived);
The thread to update the display
private class update implements Runnable{
@Override
public void run() {
while (true){
if (!messageRes.isEmpty()){
historyListModel.addElement(messageRes.poll());
}
}
}
}
Then this thread is called in the GUI main window
new Thread(new update()).start();
In order to make some tests, I tried the following code and It worked
private class update implements Runnable{
@Override
public void run() {
while (true){
Thread.sleep(1000)
historyListModel.addElement("hello world);
}
}
}
The previous code allows me to update the display every 1 second. I tried one more code in order to triangulate the error:
private class update implements Runnable{
@Override
public void run() {
while (true){
if (!messageRes.isEmpty()){
historyListModel.addElement(messageRes.poll());
historyListModel.addElement("hello world);
}
}
}
}
No display was updated with the previous code. Could anyone propose any explanation to what is happening ?
Thank you.
Swing is not thread-safe and is single-threaded. This means you should not be updating the UI from outside of the context of the Event Dispatching Thread nor should you be executing long-running/blocking calls within its context.
In your case, a
SwingWorkerwould probably be the best solution, as you can poll the queue for new messages andpublishthem to the UI in a safe manner.See...
for more details.
One thing I did note during my testing was this...
was probably causing the UI to be overloaded, as
pollwill either return the next element ornullif there are none. So it was a "wild loop". Instead, you should probably be usingtakewhich will wait till a new value is available.