I am using ThreadPoolTaskExecutor (from spring) to perform some tasks asynchronously.
The required task will load some object from the external database into my system memory. I use a maximum thread pool size of 10 and a maximum queue size of 100.
Suppose that all 10 threads are busy receiving objects from my database and tasks are created, they will go into the queue. Now another task is created, which should receive the same object (the same key in the database) from the database, it will also go into the queue (provided that all 10 threads are still busy).
Thus, my queue can be completely filled with duplicate tasks that will be performed in turn, and I do not want this to happen.
I thought the solution should come in the form of a unique collection that serves as a thread pool queue. Under the hood, ThreadPoolTaskExecutor uses a LinkedBlockingQueue, which does not provide uniqueness.
I thought of several possible solutions, but nobody satisfies me:
- Using ThreadPoolExecutor instead of ThreadPoolTaskExecutor. ThreadPoolExecutor provides a constructor that allows me to determine the type of the thread pool queue, but it needs to implement the BlockingQueue interface. I could not find an implementation that preserves uniqueness.
This made me try LinkedBlockingQueue and override add:
public boolean add(E e) if(!this.contains(e)) { return super.add(e); } else { return false; } }
But, as far as I can tell, this will lead to a significant decrease in performance, since the contains method is limited to O (n) - a bad idea.
What can solve my problem? I am aiming for good performance (in case of compromising memory performance, I do not mind abandoning memory performance).
source share