Reputation: 9111
I have a basic little chat client, i am updating multiple GUI components from a thread when the java client receives a new message from the server.
Here is the thread:
/*
* Thread class to listen for message from the server
*/
class ListenFromServer extends Thread {
public void run() {
BufferedReader in = new BufferedReader(new InputStreamReader(is));
while (true) {
try {
String tmpMsg = in .readLine().replaceAll("\\r\\n|\\r|\\n", "");
JSONObject json = new JSONObject(tmpMsg);
updateInfo(x,x,x,x,x,x,x,x,x); // Just to show
printMsg("hello world", "server", "21:20"); // prints message to JTextPane
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
So when a message is received i run the following two functions:
public void updateVisitorInfo(final String userCountry, final String userCity, final String visits, final String seType, final String seKeyword, final String trafficType, final String currentPage) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
System.out.println("UPDATE");
jLabel23.setText(userCountry + ", " + userCity);
int numberOfVisits = Integer.parseInt(visits);
if (numberOfVisits <= 1) {
jLabel33.setText("<html>First visit</html>");
} else {
jLabel33.setText("<html>Returning visit:<br><b>" + visits + "</b> visits</html>");
}
if (trafficType.contains("Direct")) {
jLabel43.setText("<html>Came from: Direct hit</html>");
} else if (trafficType.contains("Organisk")) {
jLabel43.setText("<html>Came from: " + seType + "<br />Searched keyword:<br /><b>" + seKeyword + "</b></html>");
} else if (trafficType.contains("AdWords")) {
jLabel43.setText("<html>Came from: AdWords<br />Searched keyword:<br /><b>" + seKeyword + "</b></html>");
}
jLabel53.setText("<html><div style='width:140px;'><p>Current:<br /> <a href='" + Page + "'>" + currentPage + "</a></p></div></html>");
}
});
//jLabel83.setText("<html><div style='padding-left:50px;'>Chat with " + visitorNick + "</div></html>");
}
and:
public void printMsg(final String msg, final String from, final String tid) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (msg != null && !msg.isEmpty()) {
String align = "text-align:right;";
String padd = "padding-left:12px;";
if (from.contains(agentName)) {
align = "text-align:right;";
padd = "padding-right:12px;";
} else {
align = "text-align:left;";
padd = "padding-left:12px;";
}
// Print the message
try {
kit.insertHTML(doc, doc.getLength(), "<div id=\"\" style=\"padding-top:10px;padding-bottom:10px;" + padd + "\">" + "<div id=\"\" style=\"position:relative;" + align + "\"><span style=\"color:#111111;font-weight:bold;\">" + from + "</span> at " + tid + ":</div>" + "<div id=\"\" style=\"padding-top:4px;" + align + "\">" + msg + "</div>" + "</div>", 0, 0, null);
} catch (BadLocationException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
ta.setCaretPosition(ta.getDocument().getLength()); // To scroll to the bottom of the JTextPane
}
}
});
EDIT:
JPanels
containing the components from the code above get all white so the whole app is not freezing but JPanels
are turning white
EDIT 2:
This is how i start the thread:
new ListenFromServer().start();
This code is executed when the JFrame loads (within the init()
)
EDIT 3:
Output from jstack <pid>
2013-09-09 16:41:02
Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.51-b01-457 mixed mode):
"Attach Listener" daemon prio=9 tid=7fac0f9d3800 nid=0x112bfd000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE
"Thread-8" prio=5 tid=7fac1107f800 nid=0x112f13000 waiting on condition [112f12000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at Client$SystemIdleThread.run(Client.java:1824)
"Thread-7" prio=5 tid=7fac1107f000 nid=0x112e10000 runnable [112e0f000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.DataInputStream.read(DataInputStream.java:132)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
- locked <7f4815550> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
- locked <7f4815550> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at Client$ListenFromServer.run(Client.java:2070)
"DestroyJavaVM" prio=5 tid=7fac0f1b0000 nid=0x1061d7000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE
"TimerQueue" daemon prio=5 tid=7fac0f1af000 nid=0x1122fa000 in Object.wait() [1122f9000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f481d048> (a javax.swing.TimerQueue)
at javax.swing.TimerQueue.run(TimerQueue.java:232)
- locked <7f481d048> (a javax.swing.TimerQueue)
at java.lang.Thread.run(Thread.java:680)
"AWT-EventQueue-0" prio=6 tid=7fac0e173000 nid=0x111fc6000 in Object.wait() [111fc5000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f459dc30> (a java.awt.EventQueue)
at java.lang.Object.wait(Object.java:485)
at java.awt.EventQueue.getNextEvent(EventQueue.java:558)
- locked <7f459dc30> (a java.awt.EventQueue)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:263)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
"Java2D Disposer" daemon prio=10 tid=7fac0d0de800 nid=0x111ec3000 in Object.wait() [111ec2000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f45cdcf8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked <7f45cdcf8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at sun.java2d.Disposer.run(Disposer.java:127)
at java.lang.Thread.run(Thread.java:680)
"AWT-Shutdown" prio=5 tid=7fac0f229000 nid=0x10e0b0000 in Object.wait() [10e0af000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f45cdd28> (a java.lang.Object)
at java.lang.Object.wait(Object.java:485)
at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:265)
- locked <7f45cdd28> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:680)
"AWT-AppKit" daemon prio=5 tid=7fac0f0c8800 nid=0x7fff7508a180 runnable [00000000]
java.lang.Thread.State: RUNNABLE
"Low Memory Detector" daemon prio=5 tid=7fac0f01b000 nid=0x10d9d2000 runnable [00000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=9 tid=7fac0f01a800 nid=0x10d8cf000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=9 tid=7fac0f019800 nid=0x10d7cc000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=9 tid=7fac0f019000 nid=0x10d6c9000 runnable [00000000]
java.lang.Thread.State: RUNNABLE
"Surrogate Locker Thread (Concurrent GC)" daemon prio=5 tid=7fac0f018000 nid=0x10d5c6000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=8 tid=7fac0f00d000 nid=0x10d338000 in Object.wait() [10d337000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f45cdd40> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked <7f45cdd40> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:171)
"Reference Handler" daemon prio=10 tid=7fac0f00c800 nid=0x10d235000 in Object.wait() [10d234000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f4899298> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
- locked <7f4899298> (a java.lang.ref.Reference$Lock)
"VM Thread" prio=9 tid=7fac0f008000 nid=0x10d132000 runnable
"Gang worker#0 (Parallel GC Threads)" prio=9 tid=7fac0d003800 nid=0x1095da000 runnable
"Gang worker#1 (Parallel GC Threads)" prio=9 tid=7fac0d004800 nid=0x1096dd000 runnable
"Gang worker#2 (Parallel GC Threads)" prio=9 tid=7fac0d005000 nid=0x1097e0000 runnable
"Gang worker#3 (Parallel GC Threads)" prio=9 tid=7fac0d005800 nid=0x1098e3000 runnable
"Concurrent Mark-Sweep GC Thread" prio=9 tid=7fac0e07a800 nid=0x10cda9000 runnable
"VM Periodic Task Thread" prio=10 tid=7fac0f02c800 nid=0x10dad5000 waiting on condition
"Exception Catcher Thread" prio=10 tid=7fac0d003000 nid=0x106402000 runnable
JNI global references: 2087
Any ideas what i am doing wrong here?
Upvotes: 2
Views: 328
Reputation: 53462
What you do is that you load heavy stuff from the network in one thread, then create a new thread(s) to update the user interface when something happens. Since UI can be updated only by one thread at a time, this is not something you want to do. Put your network processing in a worker thread, and when something relevant to UI happens from there, initiate a call to main UI thread to update something.
Take a look at information on this site as a whole: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
From there, you'd be interested to use a worker thread for your network communication. It would then use the publish method to update its intermediate results.
Upvotes: 3
Reputation: 30022
You are running a task that takes a long time on the Swing thread. Try profiling your code (just stick in some sysout statements) to find out where the delay is happening. Only update GUI components in the Swing thread, don't do any processing / IO in it.
Upvotes: 2