I am using Collections.Synchronizedlist()
to make my arraylist
thread safe. What I want to ask is the following code thread-safe i.e. remove while iterating over list from the end:-
pendingExecutionList = Collections.synchronizedList(new ArrayList<>(initialCapacity));
I am creating the list in main thread. and adding to this list from different threads. But, iteration and removal is being done only from a single Scheduled thread as shown below:-
for (int i = pendingExecutionList.size() - 1; i >= 0; i--)
{
if (someCondition(pendingExecutionList.get(i)))
{
process(pendingExecutionList.remove(i));
}
}
The above code is executed by only a single thread while multiple threads are adding to this list.
I want to avoid using iterator over synchronized(list)
as that is not fail-safe.
Instead holding the lock, you are actually obtaining the lock once per element. This has a risk of being slower than just holding the lock while you do your check.
I suggest you consider using a PriorityQueue with an appropriate ordering. This will order the queue so the ones you are about to process next will be at the start and the cost of removal is relatively cheap regardless of the number of waiting tasks.
If I'm understanding correctly your workflow pipeline, I would suggest trying some variant of a BlockingQueue
instead of a synchronizedList()
.
ArrayBlockingQueue
would allow you to have fair scheduling of the executions and should keep the caches of the multiple producers fairly hot (unless your producers start overtaking the cache prefetcher, in which case you'll experience false sharing).
If you are in the mood for experimenting, you can take a look at the MPSC (multiple producers, single consumer) queues available outside of the JDK, like Nitsan Wakart's MpscArrayQueue
or the Disruptor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With