3

Kotlin program snippet:

fun peek() = if (!elements.isEmpty() && elements.size > 0) elements[0] else null

It works great, but sometimes I get a firebase crash report:

Fatal Exception: java.lang.IndexOutOfBoundsException Index: 0, Size: 1 java.util.ArrayList.get (ArrayList.java:437) bigmick.ghu.util.Queue.peek (Queue.kt:17)

For me it sounds crazy: the list's size is 1, also the first (existing) element can be referred by index=0.

As far as I know it should work. But sometimes it does not.

Joni
  • 108,737
  • 14
  • 143
  • 193
BigMick
  • 56
  • 7

1 Answers1

4

The ArrayList class is not thread safe. When a thread makes a change at the same time another thread calls your method, unexpected and seemingly impossible things can happen.

A possible fix is to make it impossible for two threads to call methods of the list at the same time ("mutual exclusion"). This is easily achieved with Collections.synchronizedList

elements = Collections.synchronizedList(new ArrayList<>())

If you read elements from the list a lot more than you write, an alternative is to use CopyOnWriteArrayList instead of ArrayList

I see that you're using this code from a class called queue. In that case you may want to use an actual queue data structure instead of a list, and the standard library has many options you can choose from, depending on what behavior you want. See this question for example Choosing the best concurrency list in Java

Joni
  • 108,737
  • 14
  • 143
  • 193
  • Thanks for your clean explanation and recommendations. I guess, Collections.synchronizedList will be my friend. – BigMick Aug 10 '20 at 12:29