我有一个基本的小聊天客户端,当java客户端从服务器收到新消息时,我正在从一个线程更新多个GUI组件。
以下是主题:
/*
* 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();
}
}
}
}
因此,当收到消息时,我运行以下两个函数:
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>");
}
和
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
}
}
});
编辑:
包含上述代码中的组件的JPanels
全部为白色,因此整个应用程序都没有冻结,JPanels
正在变白
编辑2:
这就是我开始该主题的方式:
new ListenFromServer().start();
当JFrame加载时(在init()
)
编辑3:
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
我在这里做错了什么想法?
答案 0 :(得分:3)
您所做的是在一个线程中从网络加载大量内容,然后创建新线程以在发生某些事情时更新用户界面。由于UI一次只能由一个线程更新,因此这不是您想要做的事情。将您的网络处理放在工作线程中,当从那里发生与UI相关的事情时,启动对主UI线程的调用以更新某些内容。
查看整个网站上的信息:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
从那里开始,您有兴趣使用worker thread进行网络通信。然后,它将使用发布方法update its intermediate results。
答案 1 :(得分:2)
您正在运行在Swing线程上花费很长时间的任务。尝试分析您的代码(只需坚持一些sysout语句)以找出延迟发生的位置。只更新Swing线程中的GUI组件,不要在其中进行任何处理/ IO。