0

숫자 목록을 검색하여 특정 번호를 추가하는 프로그램을 작성했습니다. 거기에는 아무런 문제가 없지만, 알고리즘은 매우 효율적이고 기능적이지는 않습니다.GUI 스레드에서 Java의 '논리'스레드로 문자열을 가져올 수 없습니다.

지금은 숫자 목록을 텍스트 파일에서 가져와야하지만 사용자가 목록을 TextArea에 복사하여 붙여 넣기하고 Enter 키를 누른 다음 프로그램을 보내도록 만들려고했습니다. String를 통상의 (GUI 이외의) thread에 되돌립니다.

이렇게하려면 this example (맨 위 답변)을 따르십시오. 단추 누르기 대신 키 이벤트를 사용하고 링크 된 목록 대신 문자열을 사용하고 있습니다. 그러나 그 외에는 꽤 비슷합니다.

/*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(); 
      } 
     }); 
    } 

} 
내가 만들고 TextDemo을 실행

코드 (예, 튜토리얼 프로그램을 적용)

코드를 실행하면 입력을 누르고 프로그램이 다운 될 때까지 작동하는 것 같습니다. 에러 코드 (: http://img.photobucket.com/albums/v242/ChaosGuide/illegalmonitorstateexception.png 나는 첫 번째 5 개 라인을 포함하고있어는, 풀 버전은 여기) :

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/)를 게시하십시오. –

+0

'keyPressed' 메소드에서 ** 정확히 ** ** 수행하려고 시도 할 수있는 것을 설명 할 수 있습니까? – durron597

+0

왜 TextDemo.text는 text.notify()를 수행하고 있습니까? ? – Infested

답변

1

두 스레드는 잠금으로 demo.text를 사용하고 올바른 인 demo.text에 동기화 된 블록 내에서 의사 소통이 개체에 wait()notify()를 호출합니다. 하지만 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()를 호출 변수가 잠금으로 사용하는 경우, 그것은 최종되어야한다, 이런 종류의를 피하기 위해 곤충. 게다가, 빈 문자열을 자물쇠로 사용하는 것은 정말 나쁜 생각입니다. 너무 낮은 수준있는 약 wait()notify()을 잊고, 그리고에서 더 높은 수준의 추상화를 사용하는

private final Object lock = new Object(); 

그러나 할 수있는 가장 좋은 방법이 될 것이다 : 당신은 더 나은 것을 할 수있는 전용 개체를 만드는 것 예를 들어, semaphore와 같은 java.util.concurrent 패키지

또는 메인 스레드가 이벤트 발송 스레드를 기다리는 대신 백그라운드 스레드를 시작하거나 오랫동안 SwingWorker를 사용하여 오랜 시간 작업을 수행하는 것이 좋습니다.

+0

예 +1 .......... – mKorbel

+0

고마워요, 제가 살펴 보겠습니다. –