0

I have multiple threads of the same kind that are sharing the ArrayList:

static ArrayList<Integer> Terminate_List = new ArrayList<Integer>();

This ArrayList needs to be updated. I need to delete a single item of that list. The problem is when I reach the line

Terminate_List.remove(k);

The other thread already deleted another Item of the list, the size has decremented and I get a IndexOutOfBoundsException. So my plan was to make this method synchronized so that only one thread at a time can execute this method. The method is executed by a timer. How can I really let only one thread at a time execute this method?

    public synchronized void update_list(){

   for (int k = 0; k < Terminate_List.size(); k++) {

        if (Terminate_List.get(k) == this_ID){

            Terminate_List.remove(k); }}}
10
  • Use a static variable and put the update_list() in a loop if the static variable boolean is true then it is checked out if false then make the update. Commented Oct 15, 2014 at 20:25
  • You should synchronize all updates to the list against the same object. We can't tell if this is the case because we don't know where update_list() is. Commented Oct 15, 2014 at 20:25
  • 4
    @brso05 I'm sorry but that's a horrible idea. It is wrong but its failure won't be immediately apparent because it will work most of the time. Commented Oct 15, 2014 at 20:26
  • 2
    @Hydrophilia The probable reason is that you have several instances of whichever class update_list() is in. Without seeing more code it's impossible to tell for sure. Commented Oct 15, 2014 at 20:27
  • 1
    Or even better: use a proper collection that supports concurrency. For List, you have CopyOnWriteArrayList. But IMO it would be better using another approach for your problem like a ConcurrentHashMap instead. Commented Oct 15, 2014 at 20:30

2 Answers 2

1

Don't use remove by index - use remove by reference. This way you don't have to worry about indexes at all.

Also, Terminate_List is static, while your method is not. That means if you have multiple instances of your class, blocking will only occur where two threads area accessing the same instance. To block other threads from updating Terminate_List, you need to update how you're using synchronized.

Your code would become this:

public void update_list(){
   // your previous impl was equivalent to synchronized(this)
   synchronized (Terminate_List) {  
       Terminate_List.remove((Integer)this_ID);
   }
}

Note - I'm assuming this_ID is defined as an int - if it's already an Integer then you don't need the cast (and you'd have a problem with your equality check in your original code).

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

2 Comments

Since the list contains Integers, and this_ID is probably an int, an explicit cast would be needed here.
There's no mention in the question on what this_ID is; though based on the OP using == for comparison instead of equals, you're probably right. I'll update the answer.
0

This probably happens because you have multiple instances of whatever class update_list() is in and a static list that is used by them all. If this true, then you need to synchronize using the list as monitor:

public void update_list() {
  synchronized (terminateList) {
      // ...
  }
}

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.