2

I have a MyObject() extends Thread which creates a new MyObject of itself in the run() method. This object has a List<E> as a member, where I delete from under certain conditions.

I when creating the new Object I call start() afterwards to start it's run method. But as soon as I spawn the new Object, it throws an

Exception in thread "Thread-1" java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:73)
at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.remove(ImmutableCollections.java:80)
at mypackage.MyMainClass.MyObject.run(MyObject.java:87)  <- here I remove from my List

Example:

public class MyObject extends Thread {
    List<SomeType> list = new ArrayList<SomeType>();
    SomeType st;

    public MyObject(SomeType st) {
        this.st = st;
        // returns a List of SomeType
        list = st.getList();
    }

    @Override
    public void run() {
        while(!done) {
            SomeType toDelete;
            if (condition) {
                toDelete = st.getToDelete();
            }
            // Checks for null etc are done and not important
            for (SomeType sometype : list) {
                if (somecondition) {
                    // toDelete is always in that List
                    list.remove(toDelete)
                } 
            }

            if (lastcondition) {
                MyObject newObject = new MyObject(this.st);
                newObject.start();
            }
        }
    }
}

Why do I get this error? Since the List is a member of each instance of the Object, why is it immutable for the new Threads, but not for my initial object?

user207421
  • 305,947
  • 44
  • 307
  • 483
innuendomaximus
  • 353
  • 2
  • 3
  • 17
  • Please make a [mcve]. – Seelenvirtuose Jan 24 '20 at 11:31
  • Show your code. This doesn't make sense when you say copy – papaya Jan 24 '20 at 11:32
  • @Seelenvirtuose I added a stripped down example. I suspect the for loop being the cause for all of this. – innuendomaximus Jan 24 '20 at 12:09
  • 3
    The error says it all: you're trying to remove an element from a list which is immutable, and thus doesn't support removal. You probably want to create a mutable *copy* of `st.getList()` in the constructor. – JB Nizet Jan 24 '20 at 12:12
  • 3
    `SomeType.getList` returns a `List` implementation that does not support structural modification (or maybe no modification at all). See [this question](https://stackoverflow.com/questions/5755477/java-list-add-unsupportedoperationexception) for a similar problem (with `add()`, but the problem source and solution is very similar). – Joachim Sauer Jan 24 '20 at 12:16
  • @JoachimSauer You were right, this list gets created usin List.of() so I need to think of another way... – innuendomaximus Jan 24 '20 at 12:49
  • Creating a new object extending Thread has nothing to do with it. The object has already been created long before the error. – user207421 Jan 28 '20 at 06:25
  • You shouldn't extend `Thread`, but instead implement `Runnable`, and pass that to an instance of a normal `Thread` (or to an executor service). – Mark Rotteveel Jan 28 '20 at 07:39

2 Answers2

1

Even when you fix UnsupportedOperationException your code that removes elements from list will throw ConcurrentModificationException because you are modifying list without using iterator while traversing list using iterator

for (SomeType sometype : list) { // this creates iterator behind the scene
    if (somecondition) {
        // toDelete is always in that List
        list.remove(toDelete); // this modifies the list and makes iterator throw ConcurrentModificationException
    } 
}
Ivan
  • 8,508
  • 2
  • 19
  • 30
0

Problem was pointed out by @Joachim Sauer:

SomeType.getList returns a List implementation that does not support structural modification (or maybe no modification at all). See this question for a similar problem (with add(), but the problem source and solution is very similar).

The used list got created with List.of()which is immutable.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
innuendomaximus
  • 353
  • 2
  • 3
  • 17