2016-10-29 12 views
0

私はSwingを使用して相互排除アルゴリズムをテストするためのプラットフォームを作成しようとしています。私の意図は、GUIとGUIの間で送信されるサーバーとメッセージを表示することです。私はまた、どのサーバーが現在それにアクセスしているかを示すクリティカルセクションを表示したい。私は、SwingWorkerスレッドを実行して、ユーザーが選択したミューテックスアルゴリズムをロードするサーバーを展開するスレッドプールを使用しています。スウィングワーカースレッドが予期せずコードの実行を停止します

メッセージ表示を実装しようとするまで、プログラムは正常に動作します。各メッセージの矢印を表示するには、SwingWorker、UIArrowThreadを拡張して、ソースサーバーからターゲットに矢印を描画するJLabelを追加します。このスレッドは、JLabelを削除する前に1秒待機します。これは、明示的にこれらのメッセージの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を削除するなど、同じ結果が得られるアプローチをいくつか試しました。

更新:

私はUIが意図したとおりに機能が、それでも、元の問題が何であるか本当にわからない得ることができました。このプログラムには、サーバーからのメッセージをtextPaneに表示するメッセージングキューがあり、ここでは矢印ラベルでUIを更新すると考えました。 ArrowLabelまたはUIArrowThreadの既存のコードを変更する必要はありませんでした。

答えて

5

あなたのフラグメントは、という方法のの方法で、ArrowLabelのSwingコンポーネントを更新していることを示しています。これはスウィングsingle-thread ruleに違反します。代わりに、hereの例に示すように、バックグラウンドのサーバーにpublish()中間結果とprocess() EDTを照会します。 「このSwingWorkerのパブリッシュおよびプロセスメソッドによる中間結果を実行するために使用されるtype」の正確な定式化は、ユースケースによって異なります。具体的な例としては、TableSwingWorkerSwingWorker<MyTableModel, RowData>、公開するインスタンスはRowDataです。TableModel

+0

これは私が練習していたはずのものですが、問題を解決するものではありません。私は今までdoInBackground()からすべてを削除して、return文しか持たず、問題は解決しないようにしています。 – drosales

+0

その他のバグや報告されていない例外があるかもしれません。引用されたEDTのチェックアプローチ[here](http://stackoverflow.com/a/7788806/230513)とバグレポート[here](http:// stackoverflow)を参照してください。com/q/35154352/230513)** Update 6 **に記載されています。 – trashgod

関連する問題