Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I need a collection to store a lot of requests from many clients, and at the same time i use one thread processing all the requests stored every five seconds.so which collection should i choose in java to have the best efficiency? obviously, the collection should be thread-safe and efficiency to poll all elements every five seconds,right?
You may try to use ArrayBlockingQueue in this case.
A bounded blocking queue backed by an array. This queue orders
elements FIFO (first-in-first-out). The head of the queue is that
element that has been on the queue the longest time. The tail of the
queue is that element that has been on the queue the shortest time.
New elements are inserted at the tail of the queue, and the queue
retrieval operations obtain elements at the head of the queue.
This is a classic "bounded buffer", in which a fixed-sized array holds
elements inserted by producers and extracted by consumers. Once
created, the capacity cannot be changed. Attempts to put an element
into a full queue will result in the operation blocking; attempts to
take an element from an empty queue will similarly block.
In this there is a take method which will block, without consuming CPU cycles, until an item gets added to the queue. And it is thread safe.
I wrote a lock-free DoubleBufferedList for just this situation. Essentially, you can write to it from multiple threads and the writes will accumulate. When a read comes along the whole list is returned while, at the same time, in a thread-safe way, a new list is created for the writers to write to.
The critical difference between this and any kind of BlockingQueue is that with a Queue you will need to poll each entry out of it one-at-a-time. This structure gives you the whole accumulated list all at once, containing everything that has accumulated since the last time you looked.
public class DoubleBufferedList<T> {
// Atomic reference so I can atomically swap it through.
// Mark = true means I am adding to it so momentarily unavailable for iteration.
private AtomicMarkableReference<List<T>> list = new AtomicMarkableReference<>(newList(), false);
// Factory method to create a new list - may be best to abstract this.
protected List<T> newList() {
return new ArrayList<>();
}
// Get and replace with empty the current list - can return null - does not mean failed.
public List<T> get() {
// Atomically grab and replace the list with an empty one.
List<T> empty = newList();
List<T> it;
// Replace an unmarked list with an empty one.
if (!list.compareAndSet(it = list.getReference(), empty, false, false)) {
// Failed to replace!
// It is probably marked as being appended to but may have been replaced by another thread.
// Return empty and come back again soon.
return Collections.<T>emptyList();
}
// Successfull replaced an unmarked list with an empty list!
return it;
}
// Grab and lock the list in preparation for append.
private List<T> grab() {
List<T> it;
// We cannot fail so spin on get and mark.
while (!list.compareAndSet(it = list.getReference(), it, false, true)) {
// Spin on mark - waiting for another grabber to release (which it must).
}
return it;
}
// Release the list.
private void release(List<T> it) {
// Unmark it - should this be a compareAndSet(it, it, true, false)?
if (!list.attemptMark(it, false)) {
// Should never fail because once marked it will not be replaced.
throw new IllegalMonitorStateException("It changed while we were adding to it!");
}
}
// Add an entry to the list.
public void add(T entry) {
List<T> it = grab();
try {
// Successfully marked! Add my new entry.
it.add(entry);
} finally {
// Always release after a grab.
release(it);
}
}
// Add many entries to the list.
public void add(List<T> entries) {
List<T> it = grab();
try {
// Successfully marked! Add my new entries.
it.addAll(entries);
} finally {
// Always release after a grab.
release(it);
}
}
// Add a number of entries.
#SafeVarargs
public final void add(T... entries) {
// Make a list of them.
add(Arrays.<T>asList(entries));
}
}
A static ConcurrentHashmap with timestamp as key and request object as value would be my suggestion.
Related
I have a ConcurrentLinkedQueue that allow insertion from multiple thread however when I poll the queue, I do it in one function and I poll until the queue is empty. This can lead to an infinite loop because there can be thread inserting to the queue while I am polling.
How can I create a view of the queue and empty it before polling and still be thread safe?
One way I see is to use a ConcurrentLinkedDeque and iterating until you reach the most recently added item. You cannot do this with a single ended queue because reads look at the head first and you will need to read the tail in order to find the last added element.
The way that ConcurrentLinkedDeque works is that calls to offer(Object) and add(Object) will place the item at the tail of the queue. Calls to poll() will read the head of the queue, like so:
// Read direction --->
HEAD -> E1 -> E2 -> E3 = TAIL
// Write direction --->
As you add more items, the tail will extend to the last element, but since we want to empty the queue as we last saw it, we will grab the tail pointer and iterate until we reach the tail. We can then let subsequent iterations deal with what was added whilst we empty the queue. We peek first because using poll will remove the last added value and thus we would not be able to determine when to stop removing the elements because our marker gets removed.
ConcurrentLinkedDeque<Object> deque = new ConcurrentLinkedDeque<>();
public void emptyCurrentView() {
Object tail = deque.peekLast();
if (tail != null) {
while (true) {
// Poll the current head
Object current = deque.poll();
// Process the element
process(current);
// If we finish processing the marker
// Exit the method
if (current == tail) {
return;
}
}
}
}
You do not need to modify the producer code as the producer's default offer(Object) and add(Object) do exactly the same thing as adding the element to the tail.
How can I create a view of the queue and empty it before polling and still be thread safe?
Yeah this sounds like a really bad pattern. The whole point of using a concurrent queue implementation is that you can add to and remove from the queue at the same time. If you want to stick with ConcurrentLinkedQueue then I'd just do something like this:
// run every so often
while (true) {
// returns null immediately if the queue is empty
Item item = blockingQueue.poll();
if (item == null) {
break;
}
// process the item...
}
However, I would consider switching to use LinkedBlockingQueue instead, because it supports take(). The consumer thread would be in a loop like this:
private final BlockingQueue<Item> blockingQueue = new LinkedBlockingQueue<>();
...
while (!Thread.currentThread().isInterrupted()) {
// wait for the queue to get an item
Item item = blockingQueue.take();
// process item...
}
BlockingQueue extends Queue so the poll() loop is also available.
I want to create search mechanism which is threaded, each search thread goal is to find keyword in shared list.
Below is the example code, so do I need to synchronize the if condition or it is not necessary?
(I really don't know which part in synchronize brackets will be atomic)
class Search extends Thread {
private ArrayList<String> searchObject;
private String what;
private String name;
public Search(String name, String what,ArrayList<String> searchObject) {
this.name=name;
this.what=what;
this.searchObject=searchObject;
}
public void run() {
for(int i=0;i<searchObject.size();i++) {
synchronized (searchObject) {
if (searchObject.get(i)==what) {
System.out.println(name+": "+what+" => "+true);
}
}
}
}
}
Not only do you need to synchronize around the if block, you also need to synchronize your entire loop as well. (Which naturally means you won't see any speedup from parallelization.)
Otherwise, you could end up with:
//Assume the list is initially of length 1.
for(int i=0;i<searchObject.size();i++) { //On the first iteration, we check the if condition, and that check passes
//Before we acquire the lock, but after testing the condition, some other thread empties the list
synchronized (searchObject) {
if (searchObject.get(i)==what) {
//Whoops, we just called get(0) on a list with no contents - IndexOutOfBoundsException!
System.out.println(name+": "+what+" => "+true);
}
}
}
Or, equally worrying: if the item you're looking for is at index X initially, someone could remove items from the list when you release the lock after index X-1 - meaning your search will fail to find the thing it's looking for, even though it was in the list the entire time.
Of course, those both only apply if there's a chance your searchObject will be modified after the creation of your Thread. If you are absolutely certain the List will never be modified after it's used to construct your Search class, then you don't need any synchronization at all.
This question already has answers here:
ConcurrentModificationException (Java)
(3 answers)
Closed 9 years ago.
I have a class which stores data and gets called from many threads. It fails with a ConcurrentModificationException although every access to my Set is synchronized.
How can this happen? The synchronized should make sure that my Set is not changed while it is iterated...
Here are all functions from my class that access the Set...
Can anyone tell me what is going wrong here?
private final Object mListenerLock = new Object();
private final Set<IRetainerBaseListener> mListeners = new HashSet<IRetainerBaseListener>();
protected final void register(IRetainerBaseListener listener)
{
synchronized (mListenerLock)
{
mListeners.add(listener);
}
}
protected final boolean unregister(IRetainerBaseListener listener)
{
synchronized (mListenerLock)
{
return mListeners.remove(listener);
}
}
private final void onObjectAdded(RKey key, Object data)
{
synchronized (mListenerLock)
{
Iterator<IRetainerBaseListener> it = mListeners.iterator();
while (it.hasNext())
{
IRetainerBaseListener listener = it.next();
/* EDIT */
/* I'm not changing the Set in here, never!!! */
// I can't insert the if's, but I just check the interface class
// and call one of the following methods:
((IRetainerListener) listener).onRetainerDataAdded(key, data);
// or
((IRetainerSingleKeyListener) listener).onRetainerDataAdded(data);
}
}
}
It's not a problem of thread safety.
You are removing items while iterating on your collection. This is only possible using an iterator.
/*
* *it* does not appreciate that you removed elements
* in another way than it.remove();
* The iterator must do the add/remove operations itself
* to guarantee that it will not break the iteration.
*/
while (it.hasNext()) {
IRetainerBaseListener listener = it.next();
...
}
Synchronized is ensuring that no other thread is executing while also trying to hold a 'lock' during that operations.
Example:
Thread A:
synchronized(mListenerLock) {
doSomething;
}
Thread B:
synchronized(mListenerLock) {
doSomething;
}
This way either A or B is doing something. One have to wait for the other to release the binary 'lock' of mListenerLock.
In your case you use the very same thread to perform your actions. So you get the concurrent modification exception because you alter the state of the list (removing objects) while also iterating it.
ConcurrentModificationException does not refer to a concurrency problem in terms of threads. It is just stating that while doing one thing with a list (or related objects) your program does some other things that prevents things from working as intended. It is a (defensive) safety mechanism to prevent common bugs to happen unnoticed.
I'm implementing a concurrent skip list map based on Java's ConcurrentSkipListMap, the differences being that I want the list to allow duplicates, and I also want the list to be indexable (so that finding the Nth element of the list takes O(lg(n)) time, instead of O(n) time as with a standard skip list). These modifications aren't presenting a problem.
In addition, the skip list's keys are mutable. For example, if the list elements are the integers {0, 4, 7}, then the middle element's key can be changed to any value in [0, 7] without prompting a change to the list structure; if the key changes to (-inf, -1] or [8, +inf) then the element is removed and re-added to maintain the list order. Rather than implementing this as a removal followed by a O(lg(n)) insert, I implement this as a removal followed by a linear traversal followed by an O(1) insert (with an expected runtime of O(1) - 99% of the time the node will be swapped with an adjacent node).
Inserting a completely new node is rare (after startup), and deleting a node (without immediately re-adding it) never occurs; almost all of the operations are elementAt(i) to retrieve the element at the ith index, or operations to swap nodes after a key is modified.
The problem I'm running into is in how to implement the key modification class(es). Conceptually, I'd like to do something like
public class Node implements Runnable {
private int key;
private Node prev, next;
private BlockingQueue<Integer> queue;
public void update(int i) {
queue.offer(i);
}
public void run() {
while(true) {
int temp = queue.take();
temp += key;
if(prev.getKey() > temp) {
// remove node, update key to temp, perform backward linear traversal, and insert
} else if(next.getKey() < temp) {
// remove node, update key to temp, perform forward linear traveral, and insert
} else {
key = temp; // node doesn't change position
}
}
}
}
(The insert sub-method being called from run uses CAS in order to handle the problem of two nodes attempting to simultaneously insert at the same location (similar to how the ConcurrentSkipListMap handles conflicting inserts) - conceptually this is the same as if the first node locked the nodes adjacent to the insertion point, except that the overhead is reduced for the case where there's no conflict.)
This way I can ensure that the list is always in order (it's okay if a key update is a bit delayed, because I can be certain that the update will eventually happen; however, if the list becomes unordered then things might go haywire). The problem being that implementing the list this way will generate an awful lot of threads, one per Node (with several thousand nodes in the list) - most of them will be blocking at any given point in time, but I'm concerned that several thousand blocking threads will still result in too high of an overhead.
Another option is to make the update method synchronized and remove the Runnable interface from Node, so that rather than having two threads enqueuing updates in the Node which then takes care of processing these updates on its separate thread, the two threads would instead take turns executing the Node#update method. The problem is that this could potentially create a bottleneck; if eight different threads all decided to update the same node at once then the queue implementation would scale just fine, but the synchronized implementation would block seven out of the eight threads (and would then block six threads, then five, etc).
So my question is, how would I implement something like the queue implementation except with a reduced number of threads, or else how would I implement something like the synchronized implementation except without the potential bottleneck problem.
I think I may be able to solve this with a ThreadPoolExecutor, something like
public class Node {
private int key;
private Node prev, next;
private ConcurrentLinkedQueue<Integer> queue;
private AtomicBoolean lock = new AtomicBoolean(false);
private ThreadPoolExecutor executor;
private UpdateNode updater = new UpdateNode();
public void update(int i) {
queue.offer(i);
if(lock.compareAndSet(false, true)) {
executor.execute(updater);
}
}
private class UpdateNode implements Runnable {
public void run() {
do {
try {
int temp = key;
while(!queue.isEmpty()) {
temp += queue.poll();
}
if(prev.getKey() > temp) {
// remove node, update key to temp, perform backward linear traversal, and insert
} else if(next.getKey() < temp) {
// remove node, update key to temp, perform forward linear traveral, and insert
} else {
key = temp; // node doesn't change position
}
} finally {
lock.set(false);
}
} while (!queue.isEmpty() && lock.compareAndSet(false, true));
}
}
}
This way I have the advantages of the queue approach without having a thousand threads sitting blocked - I instead execute a UpdateNode each time I need to update a node (unless there's already an UpdateNode being executed on that Node, hence the AtomicBoolean that's acting as a lock), and rely on the ThreadPoolExecutor to make it inexpensive to create several thousand runnables.
It's plenty of questions regarding ConcurrentModificationException for ArrayList objects, but I could not find yet an answer to my problem.
In my servlet I have an ArrayList as a member object:
List myList<Object> = new ArrayList<Object> (...);
The list must be shared among users and sessions.
In one of the servlet's methods, method1, I need to iterate over the ArrayList items, and eventually add clear the list after the iteration. Here a snippet:
for (Object o : myList) {
// read item o
}
myList.clear();
In another method, method2, I simply add a new Item to the list.
Most of the times the method ends its job without errors. Sometimes, probably due to the concurrent invocation of this method by different users, I get the famous java util.ConcurrentModificationException exception.
Should I define my List as:
List myList = Collections.synchronizedList(new ArrayList(...));
Would this be enough or am I missing something? What's behind the scenes? When there is a possible concurrency, is the second thread held in standby by the container?
EDIT: I have added the answers to some comments.
Using a synchronized list will not solve your problem. The core of the problem is that you are iterating over a list and modifying it at the same time. You need to use mutual exclusion mechanisms (synchronized blocks, locks etc) to ensure that they do not happen at the same time. To elaborate, if you start with:
methodA() {
iterate over list {
}
edit list;
}
methodB() {
edit list;
}
If you use a synchronized list, what you essentially get is:
methodA() {
iterate over list {
}
synchronized {
edit list;
}
}
methodB() {
synchronized {
edit list;
}
}
but what you actually want is:
methodA() {
synchronized {
iterate over list {
}
edit list;
}
}
methodB() {
synchronized {
edit list;
}
}
Just using synchronizedList makes all methods thread safe EXCEPT Iterators.
I would use CopyOnWriteArrayList. It is thread safe and doesn't produce ConcurrentModificationException.
ConcurrentModificaitonException occurs when you attempt to modify a collection while you're iterating through it. I imagine that the error only gets thrown when you perform some conditional operation.
I'd suggest pushing the values you want to add/remove into a separate list and performing the add /remove after you're done iterating.
You need to lock not just over the method accesses but over your use of the list.
So if you allocate a paired Object like:
Object myList_LOCK = new Object();
then you can lock that object whenever you are accessing the List, like this:
synchronized(myList_LOCK) {
//Iterate through list AND modify all within the same lock
}
at the moment the only locking you're doing is within the individual methods of the List, which isn't enough in your case because you need atomicity over the entire sequence of iteration and modification.
You could use the actual object (myList) to lock rather than a paired object but in my experience you are better off using another dedicated object as it avoids unexpected deadlock conditions that can arise as a result of the code internal to the object locking on the object itself.
This is kind of an add onto Peter Lawery's answer. But since copying wouldn't effect you too negatively you can do a mixture of copying with synchronization.
private final List<Object> myList = new ArrayList<Object>();
public void iterateAndClear(){
List<Object> local = null;
synchronized(myList){
local = new ArrayList<Object>(myList);
myList.clear();
}
for(Object o : local){
//read o
}
}
public void add(Object o){
synchronized(myList){
myList.add(o);
}
}
Here you can iterate over o elements without fear of comodifications (and outside of any type of synchronization), all while myList is safely cleared and added to.