run()的Java线程问题

时间:2013-10-20 10:50:08

标签: java multithreading

我在下面定义了两个类:

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)等硬编码(如提供的代码中所示),然后就可以了。

虽然,我设法通过强制线程休眠几毫秒来解决问题,但我想知道这个问题背后的原因。

我感谢你的智慧。

注意:)

1 个答案:

答案 0 :(得分:0)

你有几个问题。

  1. 您正在从两个线程调用lstOfPendingStr上的方法,但是使用LinkedList初始化它,这不是线程安全的。您应该使用线程安全类,LinkedBlockingQueue似乎是我从您的代码中理解的最佳选项。
  2. 在您正在调用的帖子JTextArea#append()内。作为所有AWT / Swing方法,您不能从任意线程调用它们,而只能从AWT线程调用它们。将呼叫包裹在invokeLater块内。
  3. sleep似乎使代码工作的事实只是并发问题的一个标志。