run()的Java线程问题
我有两个定义如下的类:run()的Java线程问题,java,multithreading,Java,Multithreading,我有两个定义如下的类: public class TextsManager extends Thread { LinkedList<String> lstOfPendingStr = new LinkedList<String>(); boolean stopLoop = false; JTextArea txtArea; public void run() { while (!stopLoop)
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);
}
}
程序将从textField
读取用户输入,并将其传递到TextsManager.lstoffendingstr
。然后,在TextsManager.run
()中的每个循环上,它将检查lstoffendingstr
中存在的成员,并通过txtArea
输出它们
问题是,如果我删除了Thread.sleep(0)
中的run()
,那么run()
显然会停止工作。尽管已使用新元素成功更新了lstoffendingstr
,但是(!lstoffendingstr.isEmpty())时循环中的代码将永远不会被调用
在(!stopLoop)期间,我将硬代码(如System.out.println
或Thread.sleep(0)
(如提供的代码中所示)放入中,然后工作正常
虽然我通过强制线程睡眠几毫秒来解决问题,但我想知道这个问题背后的原因
我欣赏你的智慧
注意:)你有几个问题
您正在从两个线程调用lstoffendingstr
上的方法,但使用LinkedList
对其进行初始化,这不是线程安全的。您应该使用线程安全类,LinkedBlockingQueue
似乎是我从您的代码中了解到的最佳选项
在您正在调用的线程内JTextArea#append()
。与所有AWT/Swing方法一样,您不能从任意线程调用它们,只能从AWT线程调用它们。将调用包装在invokeLater
块中
sleep
似乎使代码正常工作,这只是并发问题的一个迹象。您的示例在发布时没有编译,通常看起来有点太大。请缩小它。一个猜测是,当另一个线程正在添加更新时,试图从列表中读取的线程中看不到更新。您可能希望尝试使用一个能够与多个线程协同工作的集合(请参见java.util.concurrent)。我很不确定Thread.sleep的语义,但这可能会导致内存同步,这就是为什么在添加Thread.sleep后,代码可以正常工作。在消除代码中的编译错误并使其运行后,即使删除Thread.sleep(0)
部分,我也会得到预期的输出。即使删除了这个部分,当我在JTextField中键入一些内容并按enter键时,它也会显示在JTextArea中,这里是我完成的src代码和一个可执行版本,其中我排除了Thread.sleep(0)。顺便说一下,代码在调试模式下运行良好。是发布的版本遇到了这个问题。
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("");
}
}
});
}
}