2016-04-02 10 views
0

XMLファイルから読み込んで解析したJTableを使用してGUIに追加した旅行のリストがあります。また、新しいオファーがXMLに追加されると直ちにGUIを更新するいくつかの更新機能(間隔およびクリック時に即座に)があります。私の目的は、GUIのオファーをスレッドセーフな方法で追加することです。SwingWorkerのスレッドセーフ - スレッドセーフな方法でJTableを更新

これはSwingworkerを使用してdoInBackground()を実行するクラスであり、安全性についてのより多くの懸念事項です(UpdateData.java)。 (誰かがより深く見てみたいと思っている人は、他のクラスも以下に示します)SwingUtilities.invokeLater()を使ってスレッドセーフにすることはできますか? Swingworkers done()、execute()、およびprocess()をオーバーライドすると、何らかの安全性を達成するのに役立つでしょうか?その場合どのように? (スレッドprogの初心者)(詳細を知りたい人は、他のクラスを以下に示します)。ヘルプ/フィードバックは高く評価されます。

クラス:UpdateData.java

public class UpdateData extends SwingWorker<Integer, Integer> { 

    private ArrayList<RawTravelData> listOfOffer; 
    private TravelData offerData; 
    private XMLReader parseData; 
    //the controller 
    private ControlUpdate updtController; 

    //constructor 
    public UpdateData(TravelData o, ControlUpdate offerController) { 
     updtController = offerController; 
     parseData = new XMLReader(); 
     offerData = o; 
    } 

    @Override 
    protected Integer doInBackground() throws Exception { 
     listOfOffer = parseData.fetchData(); 
     offerData.setData(listOfOffer); 
     updtController.setOfferArray(listOfOffer); 

     return null; 
    } 

} 

クラス:RawTravelData.java

public class RawTravelData { 

    private String destination = ""; 
    private String travelDate = ""; 
    private int currPrice; 

    //empty constructor 
    public RawTravelData() { 

    } 

    //setters ad getters for destination, travel date and currprise 

} 

クラス:TravelData.java

public class TravelData extends AbstractTableModel { 

    //the table header strings 
    private String[] colNames = { "Destination", "Date", "Price", "Details" }; 
    private static final long serialVersionUID = 1L; 
    //arraylist of the offer data 
    private ArrayList<RawTravelData> offerList; 

    //constructor 
    public TravelData(ArrayList<RawTravelData> rtd) { 
     offerList = rtd; 
    } 

    //second constructor to create empty list 
    public TravelData() { 
     offerList = new ArrayList<RawTravelData>(); 
    } 

    //add the list 
    public void setData(ArrayList<RawTravelData> o) { 
     offerList = o; 
     this.fireTableDataChanged(); 
    } 

    //get the offer list 
    public ArrayList<RawTravelData> getOfferList() { 
     return offerList; 
    } 

    @Override 
    public Class<?> getColumnClass(int columnIndex) { 
     switch (columnIndex) { 
     case 0: 
      return String.class; 
     case 1: 
      return Integer.class; 
     case 2: 
      return String.class; 
     case 3: 
      return String.class; 

     default: 
      break; 
     } 
     return String.class; 
    } 

    @Override 
    public int getColumnCount() { 
     return colNames.length; 
    } 

    @Override 
    public int getRowCount() { 
     return offerList.size(); 
    } 

    @Override 
    public Object getValueAt(int arg0, int arg1) { 
     switch (arg1) { 
     case 0: 
      return offerList.get(arg0).getDestination(); 
     case 1: 
      return offerList.get(arg0).getPrice(); 
     case 2: 
      return offerList.get(arg0).getTravelDate(); 
     case 3: 
      return "Details"; 
     default: 
      break; 
     } 
     return "null"; 
    } 

    @Override 
    public String getColumnName(int col) { 
     return colNames[col]; 
    } 

} 

クラス:XMLReader.java

public class XMLReader { 

    //Method to fetch and read all the data from the XML file 
    public ArrayList<RawTravelData> fetchData() { 

     //parse data and return as arraylist of offers 

     return arrayOfOffer; 
    } 
} 

クラス:ControlUpdate.java

//This class is responsible for controlling the updating of the offer data in the background 
public class ControlUpdate { 

    private TablePanel tablePane; 
    private ArrayList<RawTravelData> offerArray; 
    //.. 

    //Constructor 
    public ControlUpdate(TablePanel tablePane) { 
     settingsVal = new SaveSettings(); 

     this.tablePane = tablePane; 
     tablePane.getOfferTable().addMouseListener(
       new TableSortListener(tablePane.getOfferTable(), this)); 
     runUpdateTask(); 
     setUpdateInterval(settingsVal.readSettings()); 
    } 


    //run the updates 
    private void runUpdateTask() { 
     //used Timer and ScheduledThreadPool 
    } 

    //get the table panel 
    public TablePanel getTablePanel() { 
     return tablePane; 
    } 

    //setting the list to a new offer list for the updater 
    public void setOfferArray(ArrayList<RawTravelData> rtd) { 
     offerArray = rtd; 
    } 

} 

答えて

1

コンポーネントとそのモデルのすべての変更はありませんで、AWTイベントディスパッチスレッドで実行する必要がありますバックグラウンドスレッド。 doInBackgroundメソッドの2行目と3行目はdoneメソッド(is guaranteed to be executed in the AWT event thread)に移動する必要があります。

SwingWorkerの値のタイプをバックグラウンドで取得しているデータにすることも慣例です。

public class UpdateData 
extends SwingWorker<List<RawTravelData>, Integer> { 

    // ... 

    @Override 
    protected List<RawTravelData> doInBackground() throws Exception { 
     return parseData.fetchData(); 
    } 

    @Override 
    protected void done() { 
     try { 
      List<RawTravelData> listOfOffer = get(); 

      offerData.setData(listOfOffer); 
      updtController.setOfferArray(listOfOffer); 
     } catch (ExecutionException e) { 
      throw new RuntimeException(e); 
     } catch (InterruptedException e) { 
      // Someone wants us to exit cleanly. 
      e.printStackTrace(); 
     } 
    } 
} 
+0

ありがとう@VGR !!! btw、データ型として 'ArrayList'を使用しましたが、代わりに 'List'を使用することをお勧めしますか、式を短縮しましたか? – rubikskube

関連する問題