Thread safe of operation in one entry - java

I want to do operations like
class A {
}
ConcurrentHashMap<A, Integer> map = new ConcurrentHashMap<>();
public void fun() {
Integer count = map.get(Object);
if (count != null) {
map.put(Object, count+1);
}
}
public void add() {
// increase Object count by 1
}
public void remove() {
// deduct Object count by 1
}
How can I make fun() thread safe ?
I know a way to do this is to add synchronized block
public void fun() {
synchronized("") {
Integer count = map.get(Object);
if (count != null) {
map.put(Object, count+1);
}
}
}
But are there any other ways to do it ?
Or are there any libraries to do it ?
like thread safe entry processor ?
I also want to implement something like
public void remove() {
int count = map.get(Object);
count -= 5;
if (count <= 0) {
map.remove(Object);
} else {
map.put(Object, count + 2);
}
}
Any ways to do this ?
Thank you

Use AtomicInteger and ConcurrentHashMap.putIfAbsent()
Also look at the
ConcurrentHashMap.remove(key, value) -- removes the key only if it is mapped to the given value.
I am not sure, if it is possible to implement the exact logic (which is not very well defined in the question above), but those methods could be very useful in doing something similar.
More hints (that could be useful or may be not too much):
You (probably!) can use methods: computeIfAbsent, computeIfPresent (or replace), and remove(key, value).
ConcurrentHashMap could be defined on values are Integers.
It will be very dirty solution, and I do not recommend you to use it, but as something to think about, it could be very challenging.
Let me know if you need more hints.

Related

Check failure of putIfAbsent

Is this a valid code to write,if I wish to avoid unnecessary contains call?
I wish to avoid a contains call on every invocation,as this is highly time sensitive code.
cancelretryCountMap.putIfAbsent(tag,new AtomicInteger(0));
count = cancelretryCountMap.get(tag).incrementAndGet();
if(count > 10){
///abort after x retries
....
}
I am using JDK 7
Usually, you would use putIfAbsent like this:
final AtomicInteger present = map.get(tag);
int count;
if (present != null) {
count = present.incrementAndGet();
} else {
final AtomicInteger instance = new AtomicInteger(0);
final AtomicInteger marker = map.putIfAbsent(tag, instance);
if (marker == null) {
count = instance.incrementAndGet();
} else {
count = marker.incrementAndGet();
}
}
The reason for the explicit get being, that you want to avoid the allocation of the default value in the "happy" path (i.e., when there is already an entry with the given key).
If there is no matching entry, you have to use the return value of putIfAbsent in order to distinguish between
the entry was still missing (and the default value has been added due to the call), in which case the method returns null, and
some other thread has won the race and inserted the new entry after the call to get (in which case the method returns the current value associated with the given key)
You can abstract this sequence by introducing a helper method, e.g.,
interface Supplier<T> {
T get();
}
static <T> T computeIfAbsent(ConcurrentMap<K,T> map, T key, Supplier<? extends T> producer) {
final T present = map.get(key);
if (present != null) {
return present;
} else {
final T fallback = producer.get();
final T marker = map.putIfAbsent(key, fallback);
if (marker == null) {
return fallback;
} else {
return marker;
}
}
}
You could use this in your example:
static final Supplier<AtomicInteger> newAtomicInteger = new Supplier<AtomicInteger>() {
public AtomicInteger get() { return new AtomicInteger(0); }
};
void yourMethodWhatever(Object tag) {
final AtomicInteger counter = computeIfAbsent(cancelretryCountMap, tag, newAtomicInteger);
if (counter.incrementAndGet() > 10) {
... whatever ...
}
}
Note, that this is actually already provided in the JDK 8 as default method on Map, but since you are still on JDK 7, you have to roll your own, as is done here.

Method Enum isBigger()

I am trying to write a method in a Java enum: isBigger(Valoration val), which returns true if if the current rating is bigger than one that is passed as parameter throwing the exception ValorationNoValued if the valuations
compared (or both) is NO_VALUED.
public enum Valoracion {
NO_VALUED(0),
SO_BAD(0),
BAD(2),
OK(4),
GOOD(6),
EXCELENT(8),
WOW(10);
....
public boolean isBigger(Valoration val) throws ValorationNoValued {
if (val == NO_VALUED) {
throw new ValorationNoValued("message");
}
else {
return val.getValor() > this.valor;
}
}
}
I want to know if the current rating is NO_VALUED, but I don't know how.
You can always refer the the “current object” via this be it an enum or not. But…
It seems, your enum has a method getValor() to return the numerical value. Then it would be much cleaner to intercept the exceptional state there rather than in the comparison method:
public enum Valoracion {
NO_VALUED (0) {
#Override int getValor() {
throw new ValorationNoValued("message");
}
},
SO_BAD (0),
BAD(2),
OK (4),
GOOD (6),
EXCELENT (8),
WOW (10);
....
int getValor() {
return valorValue;
}
public boolean isBigger(Valoration val) throws ValorationNoValued {
return val.getValor()>this.getValor();
}
This way, no conditionals are needed and the symmetry between a.isBigger(b) and b.isBigger(a) comes for free.
If you prefer conditionals over overriding the method, you may still implement the getValor() method as
int getValor() {
if(this==NO_VALUED) throw new ValorationNoValued("message");
return valorValue;
}
without the need to care for two sides in the isBigger method.
Compare this:
If (this == NO_VALUED) {

How to handle concurrency in this case?

I have a HashMap
ConcurrentHashMap<String, Integer> count =new ConcurrentHashMap<String, Integer>();
I will use like this:
private Integer somefunction(){
Integer order;
synchronized (this) {
if (count.containsKey(key)) {
order = count.get(key);
count.put(key, order + 1);
} else {
order = 0;
count.put(key, order + 1);
}
}
return order;
}
But as you can see, this may not be ideal to handle concurrency, since only value under the same key may interfere each other.Different key does't interfere each other so it's not necessary to synchronize all operation. I want to synchronize only when the key is the same.
Can I do something that can achieve better performance on concurrency?
(I know ConcurrentHashMap and synchronize is kind of redundant here ,but let's focus on if we can only synchronize when key is same)
The whole point of ConcurrentHashMap is to facilitate concurrent operations. Here's how you can do an atomic update with no need for explicit synchronization:
private Integer somefunction() {
Integer oldOrder;
// Insert key if it isn't already present.
oldOrder = count.putIfAbsent(key, 1);
if (oldOrder == null) {
return 0;
}
// If we get here, oldOrder holds the previous value.
// Atomically update it.
while (!count.replace(key, oldOrder, oldOrder + 1)) {
oldOrder = count.get(key);
}
return oldOrder;
}
See the Javadocs for putIfAbsent() and replace() for details.
As Tagir Valeev points out in his answer, you can use merge() instead if you're on Java 8, which would shorten the code above to:
private Integer somefunction() {
return count.merge(key, 1, Integer::sum) - 1;
}
Another option would be to let the values be AtomicInteger instead. See hemant1900's answer for how to do so.
I think this might be better and simpler -
private final ConcurrentHashMap<String, AtomicInteger> count = new ConcurrentHashMap<String, AtomicInteger>();
private Integer someFunction(String key){
AtomicInteger order = count.get(key);
if (order == null) {
final AtomicInteger value = new AtomicInteger(0);
order = count.putIfAbsent(key, value);
if (order == null) {
order = value;
}
}
return order.getAndIncrement();
}
It's very easy if you can use Java-8:
return count.merge(key, 1, Integer::sum)-1;
No additional synchronization is necessary. The merge method is guaranteed to be executed atomically.
First of all, where does key even come from?
Secondly, if key will never be the same for two threads running that function at any one time you don't need to synchronize any part of the function.
If, however, two threads could have the same key at the same time then you only need:
synchronized(count) {
count.put(key, order + 1);
}
The reason for this is that only threaded mutation of an object variables will need to be synchronized. But the fact that you are using a ConcurrentHashMap should eliminate this problem (double check me on this), thus no synchronization is needed.
Here is how I do this,
private Integer somefunction(){
Integer order = count.compute(key, (String k, Integer v) -> {
if (v == null)
return 1;
else {
return v + 1;
}
});
return order-1;
}
This avoid keeps trying use replace(key,oldValue,newValue)
Will this be better for concurrency?
The problem is that a lot of environment doesn't support jdk8 yet.

I am trying to create a circular LinkedList Please tell me if its a correct way to do it

i have implemented logic like if i am giving a index that is not yet there then it will change the index to the reminder (Same like rotated i guess ).
import java.util.LinkedList;
public class MycircularlinkedList extends LinkedList {
private static int count = 0;
public Object get(int i) {
System.out.println("count==" + count);
if (i > count) {
i = i % count;
return super.get(i);
} else {
return super.get(i);
}
}
public boolean add(Object o) {
super.add(o);
count++;
return true;
}
public void add(int i, Object o) {
if (i > count)
i = i % count;
super.add(i, o);
count++;
}
}
A couple of points I can see:
count is static, this means you're only ever going to have one number here. Probably not what you want
count is redundant, use Collection#size()
The great thing about mod (%) is that it works for all numbers, you don't need to have the conditional. 2 % 12 == 14 % 12 == -10 % 12
If you're getting rid of the count property, you can get rid of your overridden #add(Object o) logic and just do return super.add(o);
I find some problem with your code: if count ==0 and if I use the method add(7,obj) ,then 7%0 will throw ArithmeticException.count should be declared to private since you may have two instances of your class.Also,you need to check
whether poll\offerLast method satisfies your needs,since you cant restrict
any client code to avoid using them.Finally,clone\readObject\writeObject
need to be overrried to include the count variable.
You're close.
(1) The term "circular linked list" is well-known to mean a list where the tail links back to the head (and vice versa if it's a doubly-linked list). Yours is more like a "circular buffer" stored in a linked list. We could call it LinkedListCircularBuffer or something.
(2) The class should be parameterized by the element type, thus
public class LinkedListCircularBuffer<E> extends LinkedList<E> {
#Override
public E get(int i) {
return super.get(i % size()); // simpler and faster without an "if"
}
}
(3) You can call size() instead of all the code to maintain another count.
(4) Your add(int i, Object o) method doesn't support the case where i == size(), but you can fix that by not overriding add() at all.
(5) Overridden methods need the #Override annotation.
(6) It's good style to always put braces around each "then" and "else" clause. Code like
if (i > count)
i = i % count;
is fragile, e.g. adding a println() statement into that "then" clause will break it.

How to check all members of an array

I am writing a text-based survival simulator that uses an array of Entitys. The Entity class contains data about each entity, such as energy, hydration, and morale. I'm starting to wrap up the project but I have a problem. In order to write a checkStatus() method, I need to have an if statement that checks for Entity[].isAlive on all entities, even if I don't know how long the array is. In short, how can I use an if statement to check for the value of all members of an array? I know I will probably have to use a for loop to iteratively check the members, with the array.getLength. So far I can only check variables in single classes. I have seen similar questions but they don't quite get what I'm looking for.
P.S. I'm using basic Java, with no frameworks or libraries.
Pseudo-code that demonstrates what I'm looking for
if Entity[ALL-MEMBERS].isAlive {
gameOver = true;
}
Java 6, 7, and 8:
public boolean areAllAlive(Entity[] entities) {
if(entities == null || entities.length == 0) {
return false; //?
}
for(Entity e : entities) {
if(!e.isAlive()) {
return false;
}
}
return true;
}
Java 8, using streams/functions:
public boolean areAllAlive(Entity[] entities) {
if(entities == null || entities.length == 0) {
return false; //?
}
return Arrays.stream(entities).allMatch(e -> e.isAlive());
}
First, since you probably don't know the number of Entities you are going to use before hand an ArrayList is probably a better choice. Then yes, you should use an enhanced for loop:
List<Entity> list = new ArrayList<>();
public void addEntities(){
//add Entities here
}
public boolean ifAlive(){
for (Entity e: list){
if (!e.isAlive()){
return false;
}
}
return true;
}
or something like that.
Assuming array is your entity's array, try this.:
for (int i = 0; i < array.length; i++) {
Entity entity = array[i];
if (entity.isAlive) {
gameOver = true;
//your code here
}
}

Categories