Convert synchronized methods to non-blocking algorithm - java

Just find some information about non-blocking algorithms, so want to use them in practice. I changed some code from synchronized to non-blocking, so I want to ask does I made everything right and saved previous functionality.
synchronized code:
protected PersistentState persistentState;
protected ClassConstructor(final ID id)
{
super(id);
this.persistentState = PersistentState.UNKNOWN;
}
public final synchronized PersistentState getPersistentState()
{
return this.persistentState;
}
protected synchronized void setPersistentState(final PersistentState newPersistentState)
{
if (this.persistentState != newPersistentState)
{
this.persistentState = newPersistentState;
notifyPersistentStateChanged();
}
}
my alternative in non-blocking algorithm:
protected AtomicReference<PersistentState> persistentState;
protected ClassConstructor(final ID id)
{
super(id);
this.persistentState = new AtomicReference<PersistentState>(PersistentState.UNKNOWN);
}
public final PersistentState getPersistentState()
{
return this.persistentState.get();
}
protected void setPersistentState(final PersistentState newPersistentState)
{
PersistentState tmpPersistentState;
do
{
tmpPersistentState = this.persistentState.get();
}
while (!this.persistentState.compareAndSet(tmpPersistentState, newPersistentState));
// this.persistentState.set(newPersistentState); removed as not necessary
notifyPersistentStateChanged();
}
Do I've done everything correctly, or I missed something? Any suggestions for the code and using non-blocking method for setting abject in general?

Depends what you mean by thread-safe. What do you want to happen if two threads try to write at the same time? Should one of them chosen at random be chosen as the correct new value?
This would be it at it's simplest.
protected AtomicReference<PersistentState> persistentState = new AtomicReference<PersistentState>(PersistentState.UNKNOWN);
public final PersistentState getPersistentState() {
return this.persistentState.get();
}
protected void setPersistentState(final PersistentState newPersistentState) {
persistentState.set(newPersistentState);
notifyPersistentStateChanged();
}
private void notifyPersistentStateChanged() {
}
This would still call notifyPersistentStateChanged in all cases, even if the state hasn't changed. You need to decide what should happen in that scenario (one thread makes A -> B and another goes B -> A).
If, however, you need to only call the notify if successfully transitioned the value you could try something like this:
protected void setPersistentState(final PersistentState newPersistentState) {
boolean changed = false;
for (PersistentState oldState = getPersistentState();
// Keep going if different
changed = !oldState.equals(newPersistentState)
// Transition old -> new successful?
&& !persistentState.compareAndSet(oldState, newPersistentState);
// What is it now!
oldState = getPersistentState()) {
// Didn't transition - go around again.
}
if (changed) {
// Notify the change.
notifyPersistentStateChanged();
}
}

Related

Good way to prevent duplicated event handle

I have a common problem since the first day I start coding: avoid handling an event (button click,..) multiple times. Most of the time, I come up with a simple solution (which add a boolean flag to check) like this:
private boolean isProcessingClick = false;
#Override
public void onClick(View v) {
onLoginButtonClick();
}
private void onLoginButtonClick() {
if (isProcessingClick)
return;
isProcessingClick = true;
// Do something..
// Update some UIs..
isProcessingClick = false;
}
This worked fine. But as the class go bigger with more features & events everything started going wrong. We need to create too many boolean flags which doesn't mean anything about the business and should not be a field of this class.
Does anyone has better solution for this?
The restriction can be supported with a wrapper (if you need to protect click of each button independently).
class MyOnClickListener implements View.OnClickListener {
private final View.OnClickListener internal;
private final AtomicBoolean isProcessingClick = new AtomicBoolean();
public MyOnClickListener(View.OnClickListener internal) {
this.internal = internal;
}
#Override
public void onClick(View v) {
try {
boolean noProcessing = this.isProcessingClick.compareAndSet(false, true);
if(noProcessing) {
internal.onClick(v);
} else {
// it's good to show some alert for the user here
}
} finally {
isProcessingClick.set(false);
}
}
}
I'm not android developer so AtomicBoolean was used in case that 'onClick' could be invoked by different threads.

Java delay return value

I have a situation where I read data from a YAML file that is important for the application because it is used in several classes. Here is my code:
public class CredentialsReader {
private UserCredentials credentials;
private boolean isReading = false;
public CredentialsReader() {
}
public void readCredentials() {
Runnable readerTask = new Runnable() {
#Override
public void run() {
isReading = true;
parseCredentials();
isReading = false;
System.err.println("Parsed credentials");
}
};
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(readerTask, 0, 60, TimeUnit.SECONDS);
}
private void parseCredentials() {
final File f = new File("/home/dev/IdeaProjects/server/src/main/resources/credentials.yaml");
try {
UserCredentials userCredentials = new ObjectMapper().readValue(f, UserCredentials.class);
this.credentials = userCredentials;
System.out.println(this.credentials.getUsername() + ", " + this.credentials.getPassword());
} catch (IOException e) {
e.printStackTrace();
}
}
public UserCredentials getCredentials() { return this.credentials; }
}
As you see, I read the data every minute and my question is:
Can I delay the return value of getCredentials, so when the method is called I check if isReading is true and then delay the return so I can guarantee that a caller will always get the actual state of the yaml file?
I think there are appropriate locks for similar situations, but this seems like synchronize is sufficient.
synchronized private void parseCredentials() {...}
synchronized public UserCredentials getCredentials() { ... }
By declaring those methods synchronized only one thread at a time will be able to enter the method, essentially a barrier. That means that parseCredentials could have to wait for getCredentials, but getCredentials is so trivially fast you'll never notice.
That will synchronize on an instance of CredentialReader, so if you use more than one, you might want to synchronize on something else. As mentioned it the comments it is better to synchronize on a private object rather than the instance itself. It is a small change:
public class CredentialsReader {
private UserCredentials credentials;
private boolean isReading = false;
final private Object lock = new Object();
...
Then remove the synchronize from the method signature and add a synchronize call in the body.
private void parseCredentials() {
synchronize(lock){
//original code goes here.
}
}
Also, isReading should be volatile.
I do not suggest to do it manually, you could use a CountDownLatch with init value 1 provided in jdk.
You can let the readers calls await, and let the writer calls countDown once data is prepared.
So the reader could always get fully initialized data.

Can I synchronize method by parameter

Can I synchronize method by parameter?
For example - I get person to some method and I want to do some operation for person, but if few thread call this method for the same person I want to do it one by one.
private void dosomething(Long id, Person person) {
dosomethingelse(id, person);
}
How to call dosomethingelse (id, person) only for the same id one by one? but I want that this code for different id-s can be called multithreadly
I wrote this code, but maybe something wrong here or something can be better.
public static class LatchByValue <T> {
public void latch(T value, ConsumerWithException<T> consummer) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
try {
CountDownLatch previousLatch = null;
// we are checking if another thread is already calling this method with the same id
// if sync has CountDownLatch so another thread is already calling this method
// or we put our latch and go on
while ((previousLatch = sync.putIfAbsent(value, latch)) != null) {
try {
// we are waiting for another thread, we are waiting for all threads that put their latch before our thread
previousLatch.await();
} catch (InterruptedException e) {
return;
}
}
consummer.accept(value);
} finally {
latch.countDown();
sync.remove(value, latch);
}
}
private ConcurrentHashMap<T, CountDownLatch> sync = new ConcurrentHashMap<>();
}
Example:
LatchByValue<Long> latch = new LatchByValue<>();
private void dosomething(Long id, Person person) {
latch.latch(
id,
currentId -> { dosomethingelse(currentId, person); }
);
}
Problem with using a CountdownLatch is that you can't "increment" the count so you need to replace the existing latch when it's been used, which complicates the code.
You could instead use a Semaphore with one permit which would allow you to do the same thing but in a simpler way.
Semaphore s = sync.computeIfAbsent(value, x -> new Semaphore(1, true));
s.acquire(); //this blocks and throws InterruptedException, which you need to handle
try {
consummer.accept(value);
} finally {
s.release();
}
You can use synchronized keyword on the parameter passed (culprit: it cannot be null!). And that also allows you to stop worrying about re-acquiring the lock (it's reentrant).
So the implementation would look like:
private void doSomething(Long id, Person person) {
synchronized (person) {
// do something
}
}
Remember that any other accesses (not in doSomething call) also would need to have the synchronization block, e.g.:
// another method, unrelated, but does something with 'person'
private void doSomethingElse(Person person, ... /* other arguments */) {
synchronized (person) {
// do something
}
}
It would be good document (in Person's javadoc) that the user needs to acquire the lock for that object.
If you want to provide a critical section for <id, person> tuple, you'd need to change your API a bit - and then pass that object around in your application.
private void doSomething(IdAndPerson idAndPerson) {
synchronized (idAndPerson) {
// do something
}
}
class IdAndPerson {
private final Long id;
private final Person person;
// constructor etc.
}
private static final Set<Long> lockedIds = new HashSet<>();
private void lock(Long id) throws InterruptedException {
synchronized (lockedIds) {
while (!lockedIds.add(id)) {
lockedIds.wait();
}
}
}
private void unlock(Long id) {
synchronized (lockedIds) {
lockedIds.remove(id);
lockedIds.notifyAll();
}
}
public void doSomething(Long id) throws InterruptedException {
try {
lock(id);
//Put your code here.
//For different ids it is executed in parallel.
//For equal ids it is executed synchronously.
} finally {
unlock(id);
}
}
id can be not only an 'Long' but any class with correctly overridden 'equals' and 'hashCode' methods.
try-finally - is very important - you must guarantee to unlock waiting threads after your operation even if your operation threw exception.
It will not work if your back-end is distributed across multiple servers/JVMs.

Java8 - "effectively final"

I'm using RxVertx which is a sort of RxJava along with Java8 and I have a compilation error.
Here is my code:
public rx.Observable<Game> findGame(long templateId, GameModelType game_model, GameStateType state) {
return context.findGame(templateId, state)
.flatMap(new Func1<RxMessage<byte[]>, rx.Observable<Game>>() {
#Override
public Observable<Game> call(RxMessage<byte[]> gameRawReply) {
Game game = null;
switch(game_model) {
case SINGLE: {
ebs.subscribe(new Action1<RxMessage<byte[]>>() {
#Override
public void call(RxMessage<byte[]> t1) {
if(!singleGame.contains(0) {
game = new Game(); // ERROR is at this line
singleGames.put(0, game);
} else {
game = singleGames.get(0); // ERROR is at this line
}
}
});
}
}
return rx.Observable.from(game);
}
});
}
The compilation error is:
"Local variable game defined in an enclosing scope must be final or effectively final"
I cannot define 'game' as final since I do allocation\set and return it at the end of the function.
How can I make this code compile??
Thanks.
I have a Holder class that I use for situations like this.
/**
* Make a final one of these to hold non-final things in.
*
* #param <T>
*/
public class Holder<T> {
private T held = null;
public Holder() {
}
public Holder(T it) {
held = it;
}
public void hold(T it) {
held = it;
}
public T held() {
return held;
}
public boolean isEmpty() {
return held == null;
}
#Override
public String toString() {
return String.valueOf(held);
}
}
You can then do stuff like:
final Holder<Game> theGame = new Holder<>();
...
theGame.hold(myGame);
...
{
// Access the game through the `final Holder`
theGame.held() ....
Since you need to not modify the reference of the object you can wrap the Game in something else.
The quickest (but ugly) fix is to use an array of size 1, then set the content of the array later. This works because the the array is effectively final, what is contained in the array doesn't have to be.
#Override
public Observable<Game> call(RxMessage<byte[]> gameRawReply) {
Game[] game = new Game[1];
switch(game_model) {
case SINGLE: {
ebs.subscribe(new Action1<RxMessage<byte[]>>() {
#Override
public void call(RxMessage<byte[]> t1) {
if(!singleGame.contains(0) {
game[0] = new Game();
singleGames.put(0, game[0]);
} else {
game[0] = singleGames.get(0);
}
}
});
}
}
return rx.Observable.from(game[0]);
}
Another similar option is to make a new class that has a Game field and you then set that field later.
Cyclops has Mutable, and LazyImmutable objects for handling this use case. Mutable is fully mutable, and LazyImmutable is set once.
Mutable<Game> game = Mutable.of(null);
public void call(RxMessage<byte[]> t1) {
if(!singleGame.contains(0) {
game.mutate(g -> new Game());
singleGames.put(0, game.get());
} else {
game[0] = game.mutate(g->singleGames.get(0));
}
}
LazyImmutable can be used to set a value, lazily, once :
LazyImmutable<Game> game = LazyImmutable.def();
public void call(RxMessage<byte[]> t1) {
//new Game() is only ever called once
Game g = game.computeIfAbsent(()->new Game());
}
You cant. At least not directly. U can use a wrapper class however: just define a class "GameContainer" with game as its property and foward a final reference to this container instead.
#dkatzel's suggestion is a good one, but there's another option: extract everything about retrieving/creating the Game into a helper method, and then declare final Game game = getOrCreateGame();. I think that's cleaner than the final array approach, though the final array approach will certainly work.
Although the other approaches look acceptable, I'd like to mention that you can't be sure subscribing to ebs will be synchronous and you may end up always returning null from the inner function. Since you depend on another Observable, you could just simply compose it through:
public rx.Observable<Game> findGame(
long templateId,
GameModelType game_model,
GameStateType state) {
return context.findGame(templateId, state)
.flatMap(gameRawReply -> {
switch(game_model) {
case SINGLE: {
return ebs.map(t1 -> {
Game game;
if (!singleGame.contains(0) {
game = new Game();
singleGames.put(0, game);
} else {
game = singleGames.get(0);
}
return game;
});
}
}
return rx.Observable.just(null);
});
}

GWT - Issue with property change member variable being raised while loading the data first time

I have a GWT application that loads a product when the page is loaded. I am using PropertyChangeEvent on the product object (and its sub-objects) to update the values of fields, whenever a change happens.
Of course, I do not want this PropertyChangeEvent to raise when the product is loaded for the first time. For this, I am setting the raisePropertyChange value to false, but it doesn't seem to work. Please find below the code base:
// Class ProductBaseImpl
public abstract class PropChangeImpl {
// The raise property change event, should be turned off conditionally
private boolean raisePropertyChangeEvent = true;
protected boolean getRaisePropertyChangeEvent() {
return this.raisePropertyChangeEvent;
}
protected void setRaisePropertyChangeEvent(final boolean value) {
this.raisePropertyChangeEvent = value;
}
protected void raisePropertyChangeEvent(String fieldName, Object oldValue, Object newValue) {
if (this.raisePropertyChangeEvent ) {
// --> HERE IS THE PROBLEM <--
// This IF loop must not be true when loading the product first time
System.out.println("Property change event raised!");
// the update operations go here
} else {
System.out.println("Property change event not raised!");
}
}
}
// Class ProductBaseImpl
public abstract class ProductBaseImpl extends PropChangeImpl {
private static HandlerRegistration productChangeBeginRegistration;
private static HandlerRegistration productChangeEndRegistration;
protected E instance;
protected ProductBaseImpl(final E instance) {
this.instance = instance;
// Stop updates when a new product loads
if (ProductBaseImpl.productChangeBeginRegistration == null) {
ProductBaseImpl.productChangeBeginRegistration = Core.getEventBus().addHandler(ProductChangeBeginEvent.TYPE, new ProductChangeBeginEventEventHandler() {
#Override
public void onProductChangeBegin(final ProductChangeBeginEvent event) {
ProductBaseImpl.this.raisePropertyChangeEvent(false);
}
});
}
if (ProductBaseImpl.productChangeEndRegistration == null) {
ProductBaseImpl.productChangeEndRegistration = Core.getEventBus().addHandler(ProductChangeEndEvent.TYPE, new ProductChangeEndEventtHandler() {
#Override
public void onProductChangeEnd(final ProductChangeEndEvent event) {
ProductBaseImpl.this.raisePropertyChangeEvent(true);
}
});
}
}
}
// Class ProductSubObj1
public class ProductSubObj1 extends ProductBaseImpl {
public ProductSubObj1 (final E instance) {
super(instance);
// some other operations
}
}
// similar to above, I have classes ProductSubObj1, ProductSubObj2 ...
// Class ProductProvider, that fetches the product from service to UI
public class ProductProvider {
// some properties and members
public void fetchProduct(String productId) {
// Let listeners know the product is about to change
Core.getEventBus().fireEvent(new ProductChangeBeginEvent(productId));
// Call the service to get the product in Json data
// After processing the data to be available for the UI (and scheduleDeferred)
Core.getEventBus().fireEvent(new ProductChangeEndEvent(productId));
}
}
As commented inline in the code, the control always goes within the
if (this.raiseDataChangeEvent)
block which I don't want to happen when the product is loaded for the first time.
Could you please advise what am I doing wrong?
Thanks.
Can you just do this:?
protected void raisePropertyChangeEvent(String fieldName, Object oldValue, Object newValue) {
if (this.raisePropertyChangeEvent && oldValue != null /*Or whatever your default unloaded value is*/) {
// --> HERE IS THE PROBLEM <--
// This IF loop must not be true when loading the product first time
System.out.println("Property change event raised!");
// the update operations go here
} else {
System.out.println("Property change event not raised!");
}
}

Categories

Resources