0

我在下面定义了 2 个类:

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.printlnor Thread.sleep(0)(如提供的代码中)放在 内while(!stopLoop),然后它工作正常。

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

我很欣赏你的智慧。

看待 :)

4

1 回答 1

0

你有几个问题。

  1. 您正在lstOfPendingStr从两个线程调用方法,但使用 初始化它LinkedList,这不是线程安全的。你应该使用线程安全类,LinkedBlockingQueue据我从你的代码中理解,这似乎是最好的选择。
  2. 在您正在调用的线程内JTextArea#append()。与所有 AWT/Swing 方法一样,您不能从任意线程调用它们,而只能从 AWT 线程调用它们。将调用包装在一个invokeLater块内。

sleep似乎使您的代码工作的事实只是并发问题的迹象。

于 2013-10-20T12:22:32.597 回答