簡體   English   中英

SwingWorker中的線程安全-以線程安全的方式更新JTable

[英]Threadsafety in SwingWorker - Updating JTable in a Threadsafe way

我有一個旅行報價清單,這些清單是我從XML文件讀取和解析的,並使用JTable將它們添加到我的GUI中。 我還具有一些更新功能(每隔一段時間並單擊一次),一旦將新報價添加到XML,它們就會更新GUI。 我的目標是以線程安全的方式在GUI中添加商品。

這是我使用Swingworker執行doInBackground()的類(UpdateData.java),並且更加關注安全性。 (如果有人感興趣的話,下面還會顯示其他類。 )是否可以使用SwingUtilities.invokeLater()使其具有線程安全性? 覆蓋Swingworkers的done(),execute()和process()是否會以某種方式幫助實現安全性? 在那種情況下怎么辦? (線程編的新手) (如果有人感興趣,可以在下面給出其他類)。 一些幫助/反饋將不勝感激。

類: 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;
    }

}

組件及其模型的所有修改都需要在AWT事件分配線程中執行,而不是在后台線程中執行。 doInBackground方法的第二行和第三行應移至done方法,該方法必須在AWT事件線程中執行

通常,也要讓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();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM