1

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?

1 Answer 1

1

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 IntStreams for iterations, best with no List access, just an add method in Item.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.