In java I have the following Item class
public class Item {
private final List<Integer> list = new ArrayList<>();
public synchronized List<Integer> getList() {
return list;
}
}
and I'm accessing list element of this class from multiple threads which is throwing concurrent exception error.
public class Main {
public static void main(String[] args) {
Item instance1 = new Item();
Collections.addAll(instance1.getList(),-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15);
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 1;i<=25;i ){
instance1.getList().add(i);
}
for(int i : instance1.getList()){
System.out.println(i " ");
}
thirdPartyLib(instance1.getList());//Third party library which is internally iterating over list
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 26;i<=50;i ){
instance1.getList().add(i);
}
for(int i : instance1.getList()){
System.out.println("from2 " i);
}
thirdPartyLib(instance1.getList());//Third party library which is internally iterating over list
}
}).start();
}
}
It is perfectly working with CopyOnWriteArrayList but in real scenario list is being edited many times from multiple places therefore CopyOnWriteArrayList is not the good choice for me. Also I can't use Iterator because this error is thrown by third party library which is working with list. is there any way by which I can solve this error?
CodePudding user response:
There exists Collections.synchronizedList
, however you would still need to synchronize on the list when using an Iterator, so the third party lib is problematic.
new Thread(() -> {
List<Integer> list = instance1.getList();
for(int i = 1;i<=25;i ){
list.add(i);
}
synchronized (list) {
for(int i : list){
System.out.println(i " ");
}
}
synchronized (list) {
thirdPartyLib(list);//Third party library which is internally iterating over list
}
}).start();
new Thread(() -> {
List<Integer> list = instance1.getList();
for(int i = 26;i<=50;i ){
instance1.list.add(i);
}
synchronized (list) {
for(int i : list){
System.out.println("from2 " i);
}
}
synchronized (list) {
thirdPartyLib(list);//Third party library which is internally iterating over list
}
}).start();
}
public class Item {
private final List<Integer> list = Collections.synchronizedList(new ArrayList<>());
public List<Integer> getList() {
return list;
}
}
This is quite unsatisfactory.
You could combine that CopyOnWriteArrayList
and provide independent IntStream
s for iterations, best with no List access, just an add
method in Item
.