[英]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.