0

我一直在編寫一個程序,通過搜索數字列表來查找加起來到某個其他數字的程序。這裏沒有問題,算法雖然可能效率不高,但是功能強大。無法從GUI線程獲取字符串到java中的'邏輯'線程

現在,數字列表必須從文本文件中提取,但我一直在嘗試使用戶可以將列表複製粘貼到TextArea中,並按回車鍵並讓程序發送該字符串回到正常(非GUI)線程。

這樣做我跟着this example(最佳答案)。我正在使用按鍵事件而不是按鈕按下,而使用字符串而不是鏈接列表,但除此之外,非常相似。在這裏我創建並運行TextDemo

代碼(是的,我適應的教程程序):

/*Copy paste text in window */ 
    public static String copypaste() throws Exception{ 
    String text = ""; 
    final TextDemo demo = new TextDemo(); 
    javax.swing.SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     demo.createAndShowGUI(); 
     } 
    }); 
    synchronized(demo.text){ 
     while(demo.text.equals("")){ //if the window is unused 
     demo.text.wait(); 
     } 
     text = demo.text; 
    } 
    return text; 
    } 

TextDemo本身(減去免責聲明,請不要提醒甲骨文:)):

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class TextDemo extends JPanel implements KeyListener{ 
    protected JTextArea textArea; 
    private final static String newline = "\n"; 
    public String text = ""; 
    boolean used = false; 

    public TextDemo() { 
     super(new GridBagLayout()); 

     textArea = new JTextArea(100, 30); 
     textArea.addKeyListener(this); 

     textArea.setEditable(true); 
     JScrollPane scrollPane = new JScrollPane(textArea); 

     //Add Components to this panel. 
     GridBagConstraints c = new GridBagConstraints(); 
     c.gridwidth = GridBagConstraints.REMAINDER; 

     c.fill = GridBagConstraints.BOTH; 
     c.weightx = 1.0; 
     c.weighty = 1.0; 
     add(scrollPane, c); 
    } 

    public void keyPressed(KeyEvent e) { 
     // Listen for the key pressed and check it against "Enter" 
     // Then read out of our textarea control and print to screen4  
     if (e.getKeyCode() == e.VK_ENTER) { 
      synchronized(text){ 
      text = textArea.getText(); 
      System.out.println("Text entered."); 
      text.notify(); 
      } 
      } 
    } 

    public void keyReleased(KeyEvent e) { 
     // Listen for the key pressed and check it against "Enter" 
     // Then read out of our textarea control and print to screen4  
     if (e.getKeyCode() == e.VK_ENTER) { 
      //do nothing 
     } 
    } 

    public void keyTyped(KeyEvent e) { 
     // Listen for the key pressed and check it against "Enter" 
     // Then read out of our textarea control and print to screen4  
     if (e.getKeyCode() == e.VK_ENTER) { 
      //do nothing 
     } 
    } 


    /** 
    * Create the GUI and show it. For thread safety, 
    * this method should be invoked from the 
    * event dispatch thread. 
    */ 
    public static void createAndShowGUI() { 
     //Create and set up the window. 
     JFrame frame = new JFrame("TextDemo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     //Add contents to the window. 
     frame.add(new TextDemo()); 

     //Display the window. 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     //Schedule a job for the event dispatch thread: 
     //creating and showing this application's GUI. 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 

} 

當我運行代碼時,它似乎工作,直到我敲入並且我的程序崩潰。錯誤代碼(我只包括第5行,完整版是在這裏:http://img.photobucket.com/albums/v242/ChaosGuide/illegalmonitorstateexception.png):

Exception in thread "AWT-EventQue-0" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notify(Native Method) 
    at TextDemo.keyPressed(TextDemo.java:72) 
    at java.awt.Component.processKeyEvent(Component.java:6463) 
    at javax.swing.JComponent.processKeyEvent(JComponent.java:2829) 
    at java.awt.Component.processEvent(Component.java:6282) 

這是我第一次做任何事情,即使觸及線程,所以我真不」不明白我做錯了什麼。

任何幫助,非常感謝。

+0

爲了儘快提供更好的幫助,請發佈[SSCCE](http://sscce.org/)。 – 2013-05-09 11:52:25

+0

你能解釋**完全**你在'keyPressed'方法中想要做什麼? – durron597 2013-05-09 11:55:10

+0

爲什麼TextDemo.text在做text.notify(); ? – Infested 2013-05-09 12:03:26

回答

1

兩個線程使用demo.text作爲他們的鎖,並調用wait()notify()該對象上進行通信,一個同步塊內上demo.text,這是正確的。但是在調用notify()之前,您正在爲該變量重新分配一個新值。

synchronized(text) { // this block is synchronized on the empty string object 
    text = textArea.getText(); // you assign another string to text 
    System.out.println("Text entered."); 
    text.notify(); // you call notify on this other string object, but you don't own its lock, because you synchronized on the empty string 
} 

經驗法則:所以,實際上,你的目標,你沒有自己的鎖調用notify()當一個變量作爲一個鎖,它應該是最後的,以避免這種錯誤。此外,使用空字符串作爲鎖定是一個非常糟糕的主意。你最好創建一個專用的對象要做到這一點:

private final Object lock = new Object(); 

但要做到的最好的事情是忘掉wait()notify(),這是太低級,並從使用更高級別的抽象例如,像信號量那樣的java.util.concurrent包。

甚至更​​好:不是讓主線程等待事件分派線程,而是啓動後臺線程,或者更確切地說使用SwingWorker來執行冗長的操作。

+0

是+1 .......... – mKorbel 2013-05-09 12:43:16

+0

謝謝,我會研究它。 – 2013-05-14 12:09:09