2016-10-29 2 views
0

스윙을 사용하여 상호 배제 알고리즘을 테스트 할 수있는 플랫폼을 만들려고합니다. 나의 의도는 GUI에서 그들 사이에 보내지는 서버와 메시지를 표시하는 것이다. 또한 어떤 서버가 현재 액세스하고 있는지를 보여주는 중요한 섹션을 표시하려고합니다. 사용자가 선택한 뮤텍스 알고리즘을로드하는 서버를 배포하기 위해 SwingWorker 스레드를 실행하는 스레드 풀을 사용하고 있습니다.스윙 작업자 스레드가 예기치 않게 코드 실행을 중지합니다.

메시지 표시 구현을 시도 할 때까지 예상대로 프로그램이 실행됩니다. 각 메시지의 화살표를 표시하려면 SwingWorker, UIArrowThread를 확장하여 소스 서버에서 대상으로 화살표를 그리는 JLabel을 추가하십시오. 이 스레드는 JLabel을 제거하기 전에 1 초 동안 대기합니다. 이 메시지 중 하나 이상을 명시 적으로 만들 때 (이 메시지는 특정 메시지를 작성할 수있는 테스트 플랫폼을 만들 때 유용합니다.)

이 SwingWorker 스레드를 프로그램에 통합하려고하면 문제가 발생합니다. 알고리즘이 시작되면 각 서버는 중요 섹션에 액세스하려고 시도하고 다른 서버 각각에 요청을 보냅니다. 이것은 UIArrowThread를 호출해야하지만 일부 서버 만 실제로 스레드를 생성하는 것처럼 보입니다.

public void sendMsg(int destId, Object ... objects) { 
    comm.sendMsg(destId, objects); 
    try{ 
     UIArrowThread a = new UIArrowThread(AlgorithmSimulatorUI.jlp, 
              objects[0].toString(), 
              comm.getMyId(), 
              destId); 
     AlgorithmSimulatorUI.threadPool.execute(a); 
    } catch (Exception exc){ 
     System.err.println(exc); 
    } 
} 

일부 서버는 UIArrowThread를 인스턴스화하기 직전에 실행을 중단 한 것으로 보이며 교착 상태가 발생합니다. 해당 지점을 통과하게하는 모든 서버는 정상적으로 작동하고 GUI를 있어야합니다. UIArrowThread가 호출되기 직전과 생성자에서 로깅을 테스트하고 있습니다. 실행을 멈추는 것처럼 보이는 스레드는 결코 생성자에서 로그 호출을하지 않습니다. 나는 이것이 왜 일어날 지 잘 모르겠다.

public class UIArrowThread extends SwingWorker<Integer, String>{ 

JLayeredPane jlp; 
String type; 
int source; 
int target; 
Point start; 
Point end; 
Point[] points; 
int quadrant; 

public UIArrowThread(JLayeredPane jlp, String msg_type, int source, 
        int target){ 
    this.jlp = jlp; 
    this.type = msg_type; 
    this.source = source; 
    this.target = target; 
    this.points = getPoints(); 
    this.start = points[0]; 
    this.end = points[1]; 
} 

@Override 
protected Integer doInBackground(){ 
    Point lblPoint = getLabelCoordinates(points); 
    ArrowLabel arrow = new ArrowLabel(type, 1, 2, jlp, points, quadrant); 
    if (quadrant < 5){ 
     arrow.setBounds(lblPoint.x, lblPoint.y, abs(start.x - end.x), 
         abs(start.y - end.y)); 
    } else if (quadrant < 7){ 
     arrow.setBounds(lblPoint.x, lblPoint.y, 100, abs(start.y - end.y)); 
    } else { 
     arrow.setBounds(lblPoint.x, lblPoint.y, abs(start.x - end.x), 100); 
    } 
    jlp.add(arrow); 
    String openHTML = "<html><font color='red',size=12>"; 
    String closeHTML = "</font></html>"; 
    arrow.setText(openHTML + type + closeHTML); 
    arrow.setHorizontalTextPosition(JLabel.CENTER); 
    arrow.setVerticalTextPosition(JLabel.CENTER); 
    jlp.repaint(); 
    try{ 
     Thread.sleep(arrow.lifespan); 
    } catch (Exception exc){ 
     System.err.println(exc); 
    } finally { 
     jlp.remove(arrow); 
    } 
    jlp.repaint(); 
    return 1; 
} 

이 문제의 관련 코드 부분을 추가했습니다. 위에서 언급했듯이 UIArrowThread를 제거하면 프로그램이 올바르게 실행됩니다.

doInBackground() 대신 process()에서 작업을 수행하고 제거를 수행하는 UIArrowThread 대신 ArrowLabel을 GUI에서 제거하는 것과 같은 결과를 산출하는 몇 가지 방법을 시도했습니다.

업데이트 : 내가 의도 한대로 작동하는 UI를 얻을 수 있지만, 여전히 정말 원래 문제가 무엇인지 확신했다

. 이 프로그램에는 서버의 메시지를 textPane에 표시하는 메시징 큐가있어서 여기에 화살표 레이블이있는 UI를 업데이트한다고 생각했습니다. ArrowLabel 또는 UIArrowThread의 기존 코드를 변경해야하는 것은 아닙니다.

답변

5

조각을 ArrowLabeldoInBackground() 메서드에서 SwingWorker으로 업데이트하는 것이 좋습니다. 이것은 스윙 single-thread rule을 위반합니다. 대신, here의 예제에서 볼 수 있듯이, 백그라운드 서버 (publish() 중간 결과)와 process() (EDT)을 쿼리하십시오. "이 SwingWorker의 게시 및 처리 방법으로 중간 결과를 수행하는 데 사용되는 type"의 정확한 공식은 사용 사례에 따라 다릅니다. 구체적인 예를 들어, TableSwingWorkerSwingWorker<MyTableModel, RowData>으로, 게시 인스턴스 RowDataTableModel

+0

입니다. 이것은 연습해야하는 것이지만 문제를 해결하지는 못합니다. 지금까지 doInBackground()에서 모든 것을 제거하여 return 문만 있고 문제는 여전히 지속되도록했습니다. – drosales

+0

다른 버그가 있거나보고되지 않은 예외가있을 수 있습니다. 인용 된 EDT 체크 접근법 [here] (http://stackoverflow.com/a/7788806/230513)과 버그 리포트는 [here] (http : // stackoverflow.co.kr/q/35154352/230513) ** 업데이트 6 **. – trashgod

관련 문제