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