使用java单例时,不同的方法会同时访问它,而它存储的信息会混淆
我正在为我的大学班做这个项目,它相当大。该计划的目的是促进项目学生团队的形成。它使用GUI显示团队和指标,并允许项目经理在团队中交换学生,它还有一个算法,可以找到可以改进团队指标的交换。简而言之,它找到一个时间适合度最低的团队,并找到该团队中最不适合的学生,然后它循环遍历该学生,并尝试将该最不适合的学生与另一个团队的学生交换,如果成功,它会检查指标是否改善,如果是这样的话,它会切换回原始状态,并在GUI中打印此建议。该程序有一个单独的DataStorage类,它保存学生、团队、项目的哈希图 当我从GUI控制器类调用algorithm方法时,问题就出现了:当我移动学生或使用undo按钮时,学生会被随机交换(当发生任何更改时,我调用reload()方法刷新窗口,它会调用algorithm方法)。只有在使用算法方法时才会发生这种情况,所以我想象发生的情况是算法方法获取单例实例以访问数据,它尝试执行交换以度量度量,其他一些方法获取单例实例并获取错误的状态。我已经在getInstance方法中添加了关键字“synchronized”,但没有帮助,我尝试使用ConcurrentHashMap,但没有效果 有没有人知道我做错了什么,如何帮助我?如有任何意见,我将不胜感激 这是我的单身汉:使用java单例时,不同的方法会同时访问它,而它存储的信息会混淆,java,singleton,Java,Singleton,我正在为我的大学班做这个项目,它相当大。该计划的目的是促进项目学生团队的形成。它使用GUI显示团队和指标,并允许项目经理在团队中交换学生,它还有一个算法,可以找到可以改进团队指标的交换。简而言之,它找到一个时间适合度最低的团队,并找到该团队中最不适合的学生,然后它循环遍历该学生,并尝试将该最不适合的学生与另一个团队的学生交换,如果成功,它会检查指标是否改善,如果是这样的话,它会切换回原始状态,并在GUI中打印此建议。该程序有一个单独的DataStorage类,它保存学生、团队、项目的哈希图 当我
class DataStorage{
private static DataStorage ds;
private HashMap<String, Company> companies = new HashMap<String, Company>();
private HashMap<String, Student> students = new HashMap<String, Student>();
private HashMap<String, Project> projects = new HashMap<String, Project>();
private HashMap<String, ProjectOwner> pOwners = new HashMap<String, ProjectOwner>();
private ConcurrentHashMap<String, Team> teams = new ConcurrentHashMap<String, Team>();
private DataStorage() {
}
public static synchronized DataStorage getInstance()
{
if (ds == null)
ds = new DataStorage();
return ds;
}
类数据存储{
私有静态数据存储;
私有HashMap公司=新HashMap();
private HashMap students=new HashMap();
私有HashMap项目=新建HashMap();
private HashMap pOwners=new HashMap();
私有ConcurrentHashMap团队=新ConcurrentHashMap();
私有数据存储(){
}
公共静态同步数据存储getInstance()
{
如果(ds==null)
ds=新数据存储();
返回ds;
}
下面是使用算法方法的类:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import exceptions.TeamNotFormedException;
public class ImprovementAlgo2 {
static DataStorage hv = DataStorage.getInstance();
//comparator to compare team fitness
public static Comparator<Team> createComparator(){
Comparator<Team> comp = Comparator.comparing(team -> {
try {
return team.calcTeamFitness();
} catch (TeamNotFormedException e) {
e.printStackTrace();
return null;
}
}, Double::compare);
return comp;
}
public static String giveSuggestion() throws TeamNotFormedException{
Comparator<Team> comparator = createComparator();
ArrayList<Team> sortedTeams = new ArrayList<Team>(hv.getTeams().values());
Collections.sort(sortedTeams, comparator);
double oldMixSd = 0;
double oldSDSS = 0;
try {
oldSDSS = CalculateMetrics.calcSDss();
double oldSPSF = CalculateMetrics.calcSDpspf();
double oldASSC = CalculateMetrics.calcSDassc();
oldMixSd = 0.25*oldSPSF/25 + 0.25*oldASSC + 0.5*oldSDSS;
} catch(Exception e) {}
double newMixSd;
double newSDSS;
int teamNum = 0;
int studNum = 0;
//looping only through half the teams
double maxTeamNum = hv.getTeams().size()/2;
while(teamNum <= maxTeamNum ) {
while(studNum<=4) {
//Adding all members of the worst team to an array
Team worstTeam = sortedTeams.get(0);
ArrayList<Student> sortedWorsTStudents = new ArrayList<Student>();
for (String memId : worstTeam.getMembers()) {
sortedWorsTStudents.add(hv.getStudents().get(memId));
}
//sorting student of the team based on their suitability
Comparator<Student> comp = InitialTeamSortingAlgo.createComparator(worstTeam);
Collections.sort(sortedWorsTStudents,comp);
//getting the least suitable student
Student worstStudent = sortedWorsTStudents.get(0);
boolean swapped = false;
//trying to swap least suitable student in the team with a student from another team that's more suitable
for (HashMap.Entry<String, Student> x : hv.getStudents().entrySet()) {
try {
if(x.getValue().studSuitability(worstTeam) > worstStudent.studSuitability(worstTeam)) {
swapped = DataHandling.swapTeammembers(x.getKey(), worstStudent.getID());
//checking if this improved SD, if not, we swap back and contrinue the loop
if(swapped==true) {
try {
newSDSS = CalculateMetrics.calcSDss();
//newMixSd = 0.25*CalculateMetrics.calcSDpspf()/25 + 0.25*CalculateMetrics.calcSDassc() + 0.5* CalculateMetrics.calcSDss();
}catch (Exception e) {
newSDSS = oldSDSS;
//newMixSd = oldMixSd;
}
if(newSDSS < oldSDSS) {
DataHandling.swapTeammembers(x.getKey(), worstStudent.getID());
return "Swap students " + x.getKey() + " and " + worstStudent.getID();
}
}
}
} catch (Exception e) {}
}
studNum++;
}
teamNum ++;
}
return "";
}
}
import java.util.ArrayList;
导入java.util.Collections;
导入java.util.Comparator;
导入java.util.HashMap;
导入异常。TeamNotFormedException;
公共课改进2{
静态DataStorage hv=DataStorage.getInstance();
//用于比较团队体能的比较器
公共静态比较器createComparator(){
比较器比较=比较器比较(团队->{
试一试{
return team.calcTeamFitness();
}捕获(TeamNotFormedException e){
e、 printStackTrace();
返回null;
}
}双:比较);
返回补偿;
}
公共静态字符串giveSuggestion()抛出TeamNotFormedException{
比较器比较器=createComparator();
ArrayList sortedTeams=新的ArrayList(hv.getTeams().values());
集合。排序(分类团队、比较者);
双oldMixSd=0;
双oldsds=0;
试一试{
oldSDSS=CalculateMetrics.calcSDss();
double-oldspf=CalculateMetrics.calcsdpsf();
double-oldASSC=CalculateMetrics.calcSDassc();
oldMixSd=0.25*oldspf/25+0.25*oldASSC+0.5*oldsds;
}捕获(例外e){}
双新混合SD;
双新闻决策支持系统;
int teamNum=0;
int studNum=0;
//只在一半的队伍中循环
double maxTeamNum=hv.getTeams().size()/2;
while(teamNum)
import exceptions.ExceedingMaxNumMembersException;
import exceptions.SystemException;
import exceptions.TeamNotFormedException;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javax.swing.*;
import java.net.URL;
import java.util.*;
public class GUIController implements Initializable {
private final DataStorage hv;
@FXML
private VBox mainContainer;
@FXML
private GridPane freeGrid;
@FXML
private BarChart<String, Number> percentageHist;
@FXML
private BarChart<String, Number> competencyHist;
@FXML
private BarChart<String, Number> skillGapHist;
private GridPane[] teamGrids;
@FXML
private Button undoButton;
@FXML
private Label competencyLabel;
@FXML
private Label preferenceLabel;
@FXML
private Label skillGapLabel;
@FXML
private Label suggestionLabel;
public GUIController() {
try {
hv = DataStorage.getInstance();
hv.load();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Stack<ArrayList<String>> history = new Stack <ArrayList<String>>();
Stack<ArrayList<String>> future = new Stack <ArrayList<String>>();
@Override
public void initialize(URL location, ResourceBundle resources) {
teamGrids = new GridPane[5];
for (int i = 0; i < 5; i++) {
teamGrids[i] = (GridPane) mainContainer.lookup("#team" + (i + 1) + "Grid");
}
freeGrid.setOnDragOver(event -> {
if (event.getGestureSource() != freeGrid &&
event.getDragboard().hasString()) {
event.acceptTransferModes(TransferMode.MOVE);
}
event.consume();
});
//When student is dragged to a grid above teams it gets removed from team
freeGrid.setOnDragDropped((DragEvent event) -> {
event.acceptTransferModes(TransferMode.ANY);
String s = event.getDragboard().getString();
if (event.getGestureSource() != freeGrid &&
event.getDragboard().hasString()
) {
Student student = hv.getStudents().get(s);
Team team = hv.getTeams().get(student.getTeamID());
team.removeMember(s);
//Undo-redo saving info
ArrayList<String> histEntry = new ArrayList();
histEntry.add(team.getId());
histEntry.add(student.getID());
history.push(histEntry);;
ArrayList<String> futEntry = new ArrayList();
futEntry.add(null);
futEntry.add(s);
future.push(futEntry);
reload();
}
});
Map<String, Team> teams = hv.getTeams();
List<String> teamIds = new ArrayList<>(teams.keySet());
Collections.sort(teamIds);
for (int i = 0; i < 5; i++) {
GridPane gridPane = teamGrids[i];
Label teamLabel = (Label) gridPane.lookup("#teamLabel");
String teamName = teamIds.get(i);
teamLabel.setText(teamName);
Team team = teams.get(teamName);
//Handles when student is dragged to the team
gridPane.setOnDragOver(event -> {
if (event.getGestureSource() != gridPane &&
event.getDragboard().hasString() &&
team.getMembers().size() < 4
) {
event.acceptTransferModes(TransferMode.MOVE);
}
event.consume();
});
gridPane.setOnDragDropped((DragEvent event) -> {
event.acceptTransferModes(TransferMode.ANY);
String s = event.getDragboard().getString();
if (event.getGestureSource() != gridPane &&
event.getDragboard().hasString()
) {
Student student = hv.getStudents().get(s);
String oldTeamId = student.getTeamID();
if (student.getTeamID() != null) {
Team oldTeam = hv.getTeams().get(oldTeamId);
oldTeam.removeMember(s);
student.setTeamID(null);
}
try {
//this line is called when student is draggd to a team and dropped
team.addMember(student.getID());
ArrayList histEntry = new ArrayList();
histEntry.add(oldTeamId);
histEntry.add(s);
history.push(histEntry);
ArrayList futEntry = new ArrayList();
futEntry.add(team.getId());
futEntry.add(s);
future.push(futEntry);
reload();
}
catch (Exception e) {
try {
if (!teamName.equals(student.getTeamID())) {
if (oldTeamId != null) {
Team oldTeam = hv.getTeams().get(oldTeamId);
oldTeam.addMember(student.getID());
}
}
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Add team member error");
alert.setContentText(e.getMessage());
alert.showAndWait();
}
}
});
}
reload();
}
public void undoEvent (){
if(history.size()>0) {
ArrayList<String> histItem = history.pop();
String oldteamID = (String)histItem.get(0);
String studID = (String)histItem.get(1);
//Saving current state into future stack to redo
String currentTeamID = hv.getStudents().get(studID).getTeamID();
ArrayList<String> futItem = new ArrayList();
futItem.add(currentTeamID);
futItem.add(studID);
if(currentTeamID!=null) {
Team currentTeam = hv.getTeams().get(currentTeamID);
currentTeam.removeMember(studID);
}
if(oldteamID != null) {
try {
Team oldTeam = hv.getTeams().get(oldteamID);
oldTeam.addMember(studID);
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
reload();
}}
public void redoEvent (){
if(future.size()>0) {
ArrayList<String> futItem = future.pop();
String oldteamID = (String)futItem.get(0);
String studID = (String)futItem.get(1);
//Saving current state into future stack to redo
String currentTeamID = hv.getStudents().get(studID).getTeamID();
ArrayList<String> histItem = new ArrayList();
histItem.add(currentTeamID);
histItem.add(studID);
if(currentTeamID!=null) {
Team currentTeam = hv.getTeams().get(currentTeamID);
currentTeam.removeMember(studID);
}
if(oldteamID != null) {
try {
Team oldTeam = hv.getTeams().get(oldteamID);
oldTeam.addMember(studID);
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
reload();
}}
private void reload() {
Map<String, Student> freeStudents = new HashMap<>(hv.getStudents());
freeGrid.getChildren().removeIf(node -> node.getClass() == Label.class);
for (GridPane gridPane : teamGrids) {
gridPane.getChildren().removeIf(node -> node.getClass() == Label.class && !"teamLabel".equals(node.getId()));
gridPane.setGridLinesVisible(true);
}
for (int i = 0; i < 5; i++) {
GridPane gridPane = teamGrids[i];
Label teamLabel = (Label) gridPane.lookup("#teamLabel");
Team team = hv.getTeams().get(teamLabel.getText());
List<String> memberIds = team.getMembers();;
Collections.sort(memberIds);
for (int j = 0; j < memberIds.size(); j++) {
String memberId = memberIds.get(j);
freeStudents.remove(memberId);
Student student = hv.getStudents().get(memberId);
Label memberLabel = new Label(memberId);
memberLabel.setOnDragDetected((MouseEvent event) -> {
Dragboard dragboard = memberLabel.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.putString(memberId);
dragboard.setContent(content);
event.consume();
});
GridPane.setValignment(memberLabel, VPos.CENTER);
GridPane.setHalignment(memberLabel, HPos.CENTER);
gridPane.add(memberLabel, 0, j + 1);
}
}
List<String> freeStudentIds = new ArrayList<>(freeStudents.keySet());
Collections.sort(freeStudentIds);
for (int i = 0; i < freeStudentIds.size(); i++) {
String memberId = freeStudentIds.get(i);
Student student = freeStudents.get(memberId);
student.setTeamID(null);
Label memberLabel = new Label(memberId);
memberLabel.setOnDragDetected((MouseEvent event) -> {
Dragboard dragboard = memberLabel.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.putString(memberId);
dragboard.setContent(content);
event.consume();
});
freeGrid.add(memberLabel, i / 2, i % 2);
GridPane.setValignment(memberLabel, VPos.CENTER);
GridPane.setHalignment(memberLabel, HPos.CENTER);
}
calcHists();
// displaySuggestion();
hv.save();
}
// public void displaySuggestion() {
// try {
// suggestionLabel.setText(ImprovementAlgo2.giveSuggestion());
// }catch (Exception e){
// System.out.println("Exception in displaySuggestion: " + e.getMessage());
// }
// }
private void calcHists() {
Map<String, Team> teams = hv.getTeams();
List<String> teamIds = new ArrayList<>(teams.keySet());
Collections.sort(teamIds);
percentageHist.getData().clear();
XYChart.Series<String, Number> percentageDataSeries = new XYChart.Series<>();
for (String teamId : teamIds) {
Team team = teams.get(teamId);
try {
int percentage = team.percentageFirstSecondPreferences();
percentageDataSeries.getData().add(new XYChart.Data<>(teamId, percentage));
}
catch (TeamNotFormedException e) {
System.out.println("Exception in calcHists: " + e.getMessage());
}
}
percentageHist.getData().add(percentageDataSeries);
try {
preferenceLabel.setText("SD: " + MyMath.round(CalculateMetrics.calcSDpspf(),2));
} catch (Exception e) {
e.getMessage();
}
competencyHist.getData().clear();
String[] params = {"P", "A", "W", "N"};
for (String param : params) {
XYChart.Series<String, Number> dataSeries = new XYChart.Series<>();
dataSeries.setName(param);
for (String teamId : teamIds) {
Team team = teams.get(teamId);
try {
Map<String, Double> avg = team.averageGrade();
dataSeries.getData().add(new XYChart.Data<>(teamId, avg.get(param)));
}
catch (TeamNotFormedException e) {
System.out.println("Exception in competencyHist: " + e.getMessage());
}
}
competencyHist.getData().add(dataSeries);
try {
competencyLabel.setText("SD: " + MyMath.round(CalculateMetrics.calcSDassc(),2));
} catch (Exception e) {
e.getMessage();
}
}
skillGapHist.getData().clear();
XYChart.Series<String, Number> skillGapDataSeries = new XYChart.Series<>();
for (String teamId : teamIds) {
Team team = teams.get(teamId);
try {
double skillShortfall = team.skillShortfall();
skillGapDataSeries.getData().add(new XYChart.Data<>(teamId, skillShortfall));
}
catch (TeamNotFormedException e) {
System.out.println("Exception in skillGapHist: " + e.getMessage());
}
}
skillGapHist.getData().add(skillGapDataSeries);
try {
skillGapLabel.setText("SD: " + MyMath.round(CalculateMetrics.calcSDss(),2));
} catch (Exception e) {
e.getMessage();
}
}
}