我在下面定义了两个类:
public class TextsManager extends Thread {
LinkedList<String> lstOfPendingStr = new LinkedList<String>();
boolean stopLoop = false;
JTextArea txtArea;
public void run()
{
while (!stopLoop)
{
while (!lstOfPendingStr.isEmpty())
{
String tmp = lstOfPendingStr.getFirst();
this.txtArea.append(tmp);
lstOfPendingStr.removeFirst();
}
try {
Thread.sleep(0); // note: I had to force this code
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void AddNewStr(String newStr)
{
this.lstOfPendingStr.add(newStr);
}
}
并且
public class ClientApp {
private JFrame frame;
private JTextField textField;
private JTextArea textArea;
static private TextsManager txtManager;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ClientApp window = new ClientApp();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public ClientApp() {
initialize();
/*
* Client app
*/
txtManager = new TextsManager(textArea);
txtManager.start();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
textArea = new JTextArea();
textField = new JTextField();
textField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
txtManager.AddNewStr(textField.getText() + "\n");
textField.setText("");
}
}
});
}
}
该程序将从textField
读取用户输入,并将其传递到TextsManager.lstOfPendingStr
。然后,在TextsManager.run
()内的每个循环上,它将检查lstOfPendingStr
中的现有成员并通过txtArea
输出。
问题在于,如果我删除了Thread.sleep(0)
中的代码run()
,则run()
显然已停止工作。尽管使用新元素已成功更新lstOfPendingStr
,但循环while(!lstOfPendingStr.isEmpty())
内的代码将永远不会被调用。
我在System.out.println
中放置了Thread.sleep(0)
或while(!stopLoop)
等硬编码(如提供的代码中所示),然后就可以了。
虽然,我设法通过强制线程休眠几毫秒来解决问题,但我想知道这个问题背后的原因。
我感谢你的智慧。
注意:)
答案 0 :(得分:0)
你有几个问题。
lstOfPendingStr
上的方法,但是使用LinkedList
初始化它,这不是线程安全的。您应该使用线程安全类,LinkedBlockingQueue
似乎是我从您的代码中理解的最佳选项。JTextArea#append()
内。作为所有AWT / Swing方法,您不能从任意线程调用它们,而只能从AWT线程调用它们。将呼叫包裹在invokeLater
块内。 sleep
似乎使代码工作的事实只是并发问题的一个标志。