My problem is:
I have class:
public class AtomicStringBuilder {
private final AtomicReference<StringBuilder> sbRef;
}
I need to add new characters to StringBuilder concurrently and atomically. But problem is, only last 128 characters should be in this object. I can't use StringBuffer, because operation should be non-blocking.
So,there are two operations:
First: check if StringBuilder already has 128 chars.
Second: if it has not -> add new char, if it has -> delete first char and add new char.
Is there a way to make this two or three operations atomic?
I made this method, but it doesn't work:
public void append(String string) {
this.sbRef.getAndUpdate(ref -> {
if (ref.length() < 128) {
ref.append(string);
} else {
ref.append(string).delete(0, ref.length() - 128);
}
return ref;
});
}
For testing I created this method:
public void test() {
AtomicStringBuilder atomicStringBuilder = new AtomicStringBuilder();
Random random = new Random();
Stream<Integer> infiniteStream = Stream.iterate(0, i -> random.nextInt(10));
infiniteStream.parallel()
.limit(100000)
.forEach(integer -> atomicStringBuilder.append(String.valueOf(integer)));
assertEquals(128, atomicStringBuilder.getSb().get().length());
}
This is not a real prolem, I can change AtomicReference with anything else which will work. The task is to create operation that will be lock-free and without race conditions