JavaFX8:将项目添加到 ObservableList 时出现异常:ConcurrentModificationException
JavaFX8: exception when adding items to ObservableList: ConcurrentModificationException
我有一个列出月份值的 ChoiceBox,当用户选择一个值时,它会执行此 lambda 表达式:
private TableView<IncomeFX> tableIncome;
private ChoiceBox<Month> choiceBoxIncomeMonths;
private ChangeListener<Month> setChoiceBoxIncomeMonthsBehaviour(){
ChangeListener<Month> months = (ObservableValue<? extends Month> observable, Month oldValue, Month newValue) -> {
incomesData.clear();
Year selectedYear = choiceBoxIncomeYears.getSelectionModel().getSelectedItem();
ObservableList<IncomeFX> temp = incomeManager.getIncomesOf(selectedYear, newValue);
incomesData.addAll(temp);
};
return months;
}
以及我如何添加监听器:
choiceBoxIncomeMonths.getSelectionModel().selectedItemProperty().addListener(setChoiceBoxIncomeMonthsBehaviour());
当我点击选择框时,我得到:
Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:386)
at java.util.AbstractList$Itr.next(AbstractList.java:355)
at java.util.AbstractCollection.addAll(AbstractCollection.java:343)
at javafx.collections.ModifiableObservableListBase.addAll(ModifiableObservableListBase.java:99)
at lite.money.ui.MainUI.lambda(MainUI.java:160)
at lite.money.ui.MainUI$$Lambda0/1680764266.changed(Unknown Source)
说明问题出在我调用的那一行:addAll(temp)
我该如何解决这个问题???谢谢
由于您没有发布所有代码,我猜测您是 运行 另一个试图与 JavaFX 数据交互的线程上的代码。当另一个线程尝试这样做时,它将抛出异常,因为只有 JavaFX 线程应该与数据交互。
我真的不能提供更多的建议,因为我没有你正在做的事情的完整代码库来真正说 "yes at line X you are having thread Y access location X when it should not be."
您是否将此添加到另一个线程?你会比我更了解这个应用程序,因为我没有更多的代码可以使用。
这是我解决它的方法,我知道这是一个错误的代码,但我不知道任何其他解决方案,我必须清除它两次,否则项目将被添加,就像我没有清除它一样,如果您有其他解决方案,我会很高兴:
private ChangeListener<Month> setChoiceBoxIncomeMonthsBehaviour(){
ChangeListener<Month> months = (ObservableValue<? extends Month> observable, Month oldValue, Month newValue) -> {
if (!lastMonthValuesFired) {
incomesData.clear();
Year selectedYear = choiceBoxIncomeYears.getSelectionModel().getSelectedItem();
ObservableList<IncomeFX> temp = incomeManager.getIncomesOf(selectedYear, newValue);
ObservableList<IncomeFX> temp2 = FXCollections.observableList(new ArrayList<IncomeFX>());
for (IncomeFX t : temp) {
temp2.add(t);
}
incomesData.clear();
incomesData.addAll(temp2);
}
};
return months;
}
我遇到了同样的问题并做了一些研究,这是我发现对我有用的解决方案:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* Java Program to demonstrate how to deal with
* ConcurrentModificationException.
* Unlike the name suggests, this error can come even if only
* one thread is modifying the collection e.g. List.
* It happens when you modify collection
* while iterating over it e.g. adding new element or removing elements.
*
* If you want to remove elements while traversing list then
* make sure you use Iterator's remove() method or not ArrayList's remove()
* method() to avoid ConcurrentModificationExcetpion.
*
* @author WINDOWS 8
*
*/
public class ConcurrentModExceptionDemo{
public static void main(String args[]) {
List<String> listOfPhones = new ArrayList<String>(Arrays.asList(
"iPhone 6S", "iPhone 6", "iPhone 5", "Samsung Galaxy 4",
"Lumia Nokia"));
System.out.println("list of phones: " + listOfPhones);
// Iterating and removing objects from list
// This is wrong way, will throw ConcurrentModificationException
for(String phone : listOfPhones){
if(phone.startsWith("iPhone")){
// listOfPhones.remove(phone); // will throw exception
}
}
// The Right way, iterating elements using Iterator's remove() method
for(Iterator<String> itr = listOfPhones.iterator();
itr.hasNext();){
String phone = itr.next();
if(phone.startsWith("iPhone")){
// listOfPhones.remove(phone); // wrong again
itr.remove(); // right call
}
}
System.out.println("list after removal: " + listOfPhones);
}
}
我有一个列出月份值的 ChoiceBox,当用户选择一个值时,它会执行此 lambda 表达式:
private TableView<IncomeFX> tableIncome;
private ChoiceBox<Month> choiceBoxIncomeMonths;
private ChangeListener<Month> setChoiceBoxIncomeMonthsBehaviour(){
ChangeListener<Month> months = (ObservableValue<? extends Month> observable, Month oldValue, Month newValue) -> {
incomesData.clear();
Year selectedYear = choiceBoxIncomeYears.getSelectionModel().getSelectedItem();
ObservableList<IncomeFX> temp = incomeManager.getIncomesOf(selectedYear, newValue);
incomesData.addAll(temp);
};
return months;
}
以及我如何添加监听器:
choiceBoxIncomeMonths.getSelectionModel().selectedItemProperty().addListener(setChoiceBoxIncomeMonthsBehaviour());
当我点击选择框时,我得到:
Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:386)
at java.util.AbstractList$Itr.next(AbstractList.java:355)
at java.util.AbstractCollection.addAll(AbstractCollection.java:343)
at javafx.collections.ModifiableObservableListBase.addAll(ModifiableObservableListBase.java:99)
at lite.money.ui.MainUI.lambda(MainUI.java:160)
at lite.money.ui.MainUI$$Lambda0/1680764266.changed(Unknown Source)
说明问题出在我调用的那一行:addAll(temp) 我该如何解决这个问题???谢谢
由于您没有发布所有代码,我猜测您是 运行 另一个试图与 JavaFX 数据交互的线程上的代码。当另一个线程尝试这样做时,它将抛出异常,因为只有 JavaFX 线程应该与数据交互。
我真的不能提供更多的建议,因为我没有你正在做的事情的完整代码库来真正说 "yes at line X you are having thread Y access location X when it should not be."
您是否将此添加到另一个线程?你会比我更了解这个应用程序,因为我没有更多的代码可以使用。
这是我解决它的方法,我知道这是一个错误的代码,但我不知道任何其他解决方案,我必须清除它两次,否则项目将被添加,就像我没有清除它一样,如果您有其他解决方案,我会很高兴:
private ChangeListener<Month> setChoiceBoxIncomeMonthsBehaviour(){
ChangeListener<Month> months = (ObservableValue<? extends Month> observable, Month oldValue, Month newValue) -> {
if (!lastMonthValuesFired) {
incomesData.clear();
Year selectedYear = choiceBoxIncomeYears.getSelectionModel().getSelectedItem();
ObservableList<IncomeFX> temp = incomeManager.getIncomesOf(selectedYear, newValue);
ObservableList<IncomeFX> temp2 = FXCollections.observableList(new ArrayList<IncomeFX>());
for (IncomeFX t : temp) {
temp2.add(t);
}
incomesData.clear();
incomesData.addAll(temp2);
}
};
return months;
}
我遇到了同样的问题并做了一些研究,这是我发现对我有用的解决方案:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* Java Program to demonstrate how to deal with
* ConcurrentModificationException.
* Unlike the name suggests, this error can come even if only
* one thread is modifying the collection e.g. List.
* It happens when you modify collection
* while iterating over it e.g. adding new element or removing elements.
*
* If you want to remove elements while traversing list then
* make sure you use Iterator's remove() method or not ArrayList's remove()
* method() to avoid ConcurrentModificationExcetpion.
*
* @author WINDOWS 8
*
*/
public class ConcurrentModExceptionDemo{
public static void main(String args[]) {
List<String> listOfPhones = new ArrayList<String>(Arrays.asList(
"iPhone 6S", "iPhone 6", "iPhone 5", "Samsung Galaxy 4",
"Lumia Nokia"));
System.out.println("list of phones: " + listOfPhones);
// Iterating and removing objects from list
// This is wrong way, will throw ConcurrentModificationException
for(String phone : listOfPhones){
if(phone.startsWith("iPhone")){
// listOfPhones.remove(phone); // will throw exception
}
}
// The Right way, iterating elements using Iterator's remove() method
for(Iterator<String> itr = listOfPhones.iterator();
itr.hasNext();){
String phone = itr.next();
if(phone.startsWith("iPhone")){
// listOfPhones.remove(phone); // wrong again
itr.remove(); // right call
}
}
System.out.println("list after removal: " + listOfPhones);
}
}