2014-09-05 2 views
-1

이 코드에서는 두 개의 스레드가 실행 중이며 버튼을 처음 클릭 할 때 두 번째 스레드를 알리고 있습니다. 통보를 받으면 도움을 받으십시오.자바에서 스레드가 알리지 않고 있습니다

import java.awt.Color; 
import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.SwingWorker; 



public class Main implements ActionListener { 


    JButton button = new JButton("Click"); 
    JFrame frame = new JFrame(); 
    boolean wait=false; 
    Counter c[] = new Counter[2]; 

    public static void main(String arg[]) { 
     new Main(); 
    } 

    public Main() { 
     frame.setLayout(new FlowLayout()); 
     frame.getContentPane().setBackground(Color.BLACK); 
     frame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
     button.addActionListener(this); 
     frame.add(button); 
     frame.setVisible(true); 
     c[0]=new Counter(); 
     c[0].execute(); 
     c[1]=new Counter(); 
     c[1].execute(); 
    } 

    public class Counter extends SwingWorker<Void, Void> { 

     JLabel label = new JLabel(); 

     public Counter() { 
      label.setForeground(Color.WHITE); 
      frame.add(label); 
     } 

     public Void doInBackground() { 
      synchronized (this) { 
       for(int i=0; i!=-1; i++) { 
        if(wait==true) 
         try {this.wait();} catch(Exception exp) {exp.printStackTrace();} 
        label.setText(""+i); 
        try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}  
       } 
      } 
      return null; 
     } 
    } 

    public void actionPerformed(ActionEvent clicked) { 
     if(wait==false) 
      wait=true; 
     else if(wait==true) { 
      synchronized (c) { 
       c.notifyAll(); 
      } 
      wait=false; 
     } 
    } 

} 

답변

1

알림과 동일한 개체를 기다려야합니다.

notifyAll()의 호출은 c에서 수행됩니다. this.wait()으로 전화 할 때 thisc[0]c[1]의 두 카운터를 나타냅니다. c[0]c[1]은 배열 c과 동일한 개체가 아니기 때문에 문제가됩니다.

thisc으로 바꿉니다.

public Void doInBackground() { 
    try { 
     for (int i = 0; i != -1; i++) { 
      synchronized (c) { 
       // Check the wait condition in a loop to guard against spurious 
       // wakeups. 
       while (wait == true) { 
        c.wait(); 
       } 
      } 

      label.setText("" + i); 
      Thread.sleep(200); 
     } 
    } 
    catch (InterruptedException exception) { 
     // Exit the loop if the thread is interrupted. 
    } 

    return null; 
} 

은 나뿐만 아니라 다른 개선을했다 :

  1. wait() 기능은 의사를 깨우는가 발생할 수 있습니다. 일반적으로 다른 스레드가 notify()을 호출했을 때만 반환되지만, 특별한 이유없이 wait()이 반환 될 수 있습니다. 그건 가짜 웨이크 업이야. 가짜 웨이크 업을 방지하려면 항상 wait()으로 전화를 걸어 대기 상태를 확인해야합니다.

  2. 나는 가능한 한 많이 synchronized 블록의 범위를 줄였다. 거기에있을 때 다른 스레드를 차단하게되므로 가능한 한 빨리 들어가야합니다. 거기에서 무거운 물건을 들지 마십시오. 잠금을 유지하면서 GUI 코드를 호출하지 마십시오. 동기화 된 블록 안에서 잠을 자지 마십시오.

관련 문제