Is it possible to add multiple actions to a CompletableFuture with whenComplete(...)? - java

The class CompletableFuture allows to add an action which is called when the future completes after calling complete(...).
Can I use whenComplete(...) to add multiple BiConsumer actions for executing when completing the future and are all of them executed when the complete(...) method is called?

Yes, all BiConsumer actions are added and they are executed in reverse addition order when calling complete(...).
An example to demonstrate this might look like this:
public class Application {
public static void main(String[] args) {
System.out.println("My tests ...");
CompletableFuture<String> futureString = new CompletableFuture<String>();
futureString.whenComplete((s,e)->System.out.println("one " + s));
futureString.whenComplete((s,e)->System.out.println("two " + s));
futureString.whenComplete((s,e)->System.out.println("three " + s));
System.out.println("do something else; "+ futureString.isDone());
futureString.complete("step(s)");
System.out.println("Done " + futureString.isDone());
}
}
When running this program, the printed result looks this:
My tests ...
do something else; false
three step(s)
two step(s)
one step(s)
Done true

Related

RxJava Flowable cache to Single deadlock

Below is my code snippet.
I know you are not supposed to block cachedFlowable like this, but this is just an example.
It gets stuck at the blockingGet line.
If I replace singleOrError with singleElement, the code will still get stuck. If I replace singleOrError with firstElement, the code will no longer get stuck.
Can someone please explain to me why this is the case?
public static void main(String[] args) {
final Flowable<Integer> cachedFlowable = Flowable.just(1).cache();
cachedFlowable
.doOnNext(i -> {
System.out.println("doOnNext " + i);
final Integer j = cachedFlowable.singleOrError().blockingGet();
System.out.println("after blockingGet " + j);
})
.blockingSubscribe();
}
The reason it deadlocks with singleX operator is that such operators wait for a possible 2nd item emission but since you are blocking them, any second item or completion from the main source can't get executed. With firstX they only care about the very first item thus unblock almost immediately which allows the source to complete.
So yes, you should not use blocking methods in flows like that but instead use flatMap or concatMap to do a per item subflow:
var cache = Flowable.just(1).cache();
cache
.doOnNext(i -> System.out.println("doOnNext " + i))
.concatMapSingle(item -> cache.firstOrError())
.doOnNext(j -> System.out.println("after " + j))
.blockingSubscribe();

thenApply in CompletableFuture

In the following code
public CompletableFuture<String> getMyFuture(String input)
{
CompletableFuture<String> future = new CompletableFuture<String>().thenApply((result) -> result+ "::");
ExecutorService service = Executors.newFixedThreadPool(6);
service.submit(() -> {
try {
future.complete(getResult(input));
} catch (InterruptedException e) {
e.printStackTrace();
}
});
return future;
}
public String getResult(String input) throws InterruptedException
{
Thread.sleep(3000);
return "hello "+ input +" :" + LocalTime.now();
}
I am expecting the output to contain trailing "::" but program doesn't is "hello first :16:49:30.231
" Is my implementation of apply correct ?
You're invoking complete() method of the CompletionStage that you got at the first line (where you call "thenApply" method).
If your intention is to complete the CompletableFuture with some string value (future.complete(getResult(input))) and then apply some function, you'd better place thenApply() at the end (where you return the future).
public CompletableFuture<String> getMyFuture(String input)
{
CompletableFuture<String> future = new CompletableFuture<String>();
ExecutorService service = Executors.newFixedThreadPool(6);
service.submit(() -> {
try {
future.complete(getResult(input));
} catch (InterruptedException e) {
e.printStackTrace();
}
});
return future.thenApply(result -> result+ "::");
}
I don't know how to explain it in a more understandable way. But in short: you're calling complete() method on the wrong object reference inside your Runnable.
You are creating two CompletableFuture instances. The first, created via new CompletableFuture<String>() will never get completed, you don’t even keep a reference to it that would make completing it possible.
The second, created by calling .thenApply((result) -> result+ "::") on the first one, could get completed by evaluating the specified function once the first one completed, using the first’s result as an argument to the function. However, since the first never completes, the function becomes irrelevant.
But CompletableFuture instances can get completed by anyone, not just a function passed to a chaining method. The possibility to get completed is even prominently displayed in its class name. In case of multiple completion attempts, one would turn out to be the first one, winning the race and all subsequent completion attempts will be ignored. In your code, you have only one completion attempt, which will successfully complete it with the value returned by getResult, without any adaptations.
You could change your code to keep a reference to the first CompletableFuture instance to complete it manually, so that the second gets completed using the function passed to thenApply, but on the other hand, there is no need for manual completion here:
public CompletableFuture<String> getMyFuture(String input) {
ExecutorService service = Executors.newFixedThreadPool(6);
return CompletableFuture.supplyAsync(() -> getResult(input), service)
.thenApply(result -> result + "::");
}
public String getResult(String input) {
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
return "hello "+ input +" :" + LocalTime.now();
}
When specifying the executor to supplyAsync, the function will be evaluated using that executor. More is not needed.
Needless to say, that’s just for example. You should never create a temporary thread pool executor, as the whole point of a thread pool executor is to allow reusing the threads (and you’re using only one of these six threads at all) and it should get shut down after use.

Disable Thread.sleep()

I want to disable possibility of using Thread.sleep() in a java project and use my own method instead:
sleep(int time, String info)
That will wait for given amount of time, and print info why is waiting necessary here.
Is disabling Thread.sleep() possible?
If yes, what's best method to do so?
The best method would be to have hook on some static code analysis tool to mark build as failed if there are any invocations of Thread.Sleep().
You could probably configure SonarCube to do this.
You can use AOP to intercept calls to Thread.sleep() and "redirect" call to your one via aroundAdvice. When original Thread.sleep() is invoked, a "default cause" is added. This one shows an example about how you can use it (remember to create a AspectJ project, or Aspects will not work):
SleepAspect.java
package org.norsam.so.sleep
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class SleepAspect
{
#Around("call (* java.lang.Thread.sleep(..) )")
public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable
{
StackTraceElement ste = Thread.currentThread().getStackTrace()[2];
Long ms = (Long) point.getArgs()[0];
String m = ste.getMethodName();
String c = ste.getClassName();
String skip = SleepClass.class.getName();
if (c.equals(skip) && m.equals("sleep")) {
System.out.println("sleep well for " + ms + "ms!");
} else {
SleepClass.sleep(ms, "Thread.sleep invoked in " + c + "." + m + ", no cause present!");
}
Object toret = point.proceed();
return toret;
}
}
SleepClass.java
package org.norsam.so.sleep
public class SleepClass {
public static void sleep(long l, String cause) {
System.out.println("CAUSE: " + cause);
try {
Thread.sleep(l);
} catch (InterruptedException e) {
}
}
public static void main(String[] args) throws InterruptedException {
SleepClass.sleep(1000, "I love to sleep 1000");
Thread.sleep(2000L);
System.out.println("Bye");
}
}
When you run it, you receive something like
CAUSE: I love to sleep 1000
sleep well for 1000ms!
CAUSE: Thread.sleep invoked in org.norsam.so.sleep.SleepClass.main, no cause present!
sleep well for 2000ms!
Bye
Yes, sure.
Just make sure that no code in that project is calling Thread.sleep(); but your MyUtility.sleep() replacement.
If the question is: can I somehow change the behavior of the existing Thread.sleep(), then the answer is: depends on context/effort you are willing to spend.
Well, with certain tricks; it might be possible; but simply speaking: it is a most likely a bad idea; and not worth following up on. I would really shy away from changing the code behavior, if at all I would look into those solutions that can identify usages of that unwanted sleep calls at compile time.

Are JavaFX Property objects threadsafe for multiple asynchronous writes?

Is it dangerous for the standard implementations of Property in JavaFX to call set methods from multiple threads? I don't really care about race conditions on the client side from reading-and-then-setting operations. I want to know if the Property itself can be corrupted internally if multiple threads call its set() or setValue() method.
Is this code below threadsafe?
public class ThreadSafeProperty {
public static void main(String[] args) {
ObjectProperty<Integer> property = new SimpleObjectProperty<>(5);
ExecutorService exec = Executors.newFixedThreadPool(5);
property.addListener((obs,o,n) -> System.out.println("OLD: " + o + " NEW: " + n));
exec.execute(() -> property.set(4));
exec.execute(() -> property.set(6));
exec.execute(() -> property.set(11));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
exec.shutdown();
}
}
SimpleObjectProperty is not thread safe.
You see this in the source: javafx/beans/property/ObjectPropertyBase.set is not synchronized, or you use a tool like http://vmlens.com witch looks for you:-)

Generate infinite sequence of Natural numbers using RxJava

I am trying to write a simple program using RxJava to generate an infinite sequence of natural numbers. So, far I have found two ways to generate sequence of numbers using Observable.timer() and Observable.interval(). I am not sure if these functions are the right way to approach this problem. I was expecting a simple function like one we have in Java 8 to generate infinite natural numbers.
IntStream.iterate(1, value -> value +1).forEach(System.out::println);
I tried using IntStream with Observable but that does not work correctly. It sends infinite stream of numbers only to first subscriber. How can I correctly generate infinite natural number sequence?
import rx.Observable;
import rx.functions.Action1;
import java.util.stream.IntStream;
public class NaturalNumbers {
public static void main(String[] args) {
Observable<Integer> naturalNumbers = Observable.<Integer>create(subscriber -> {
IntStream stream = IntStream.iterate(1, val -> val + 1);
stream.forEach(naturalNumber -> subscriber.onNext(naturalNumber));
});
Action1<Integer> first = naturalNumber -> System.out.println("First got " + naturalNumber);
Action1<Integer> second = naturalNumber -> System.out.println("Second got " + naturalNumber);
Action1<Integer> third = naturalNumber -> System.out.println("Third got " + naturalNumber);
naturalNumbers.subscribe(first);
naturalNumbers.subscribe(second);
naturalNumbers.subscribe(third);
}
}
The problem is that the on naturalNumbers.subscribe(first);, the OnSubscribe you implemented is being called and you are doing a forEach over an infinite stream, hence why your program never terminates.
One way you could deal with it is to asynchronously subscribe them on a different thread. To easily see the results I had to introduce a sleep into the Stream processing:
Observable<Integer> naturalNumbers = Observable.<Integer>create(subscriber -> {
IntStream stream = IntStream.iterate(1, i -> i + 1);
stream.peek(i -> {
try {
// Added to visibly see printing
Thread.sleep(50);
} catch (InterruptedException e) {
}
}).forEach(subscriber::onNext);
});
final Subscription subscribe1 = naturalNumbers
.subscribeOn(Schedulers.newThread())
.subscribe(first);
final Subscription subscribe2 = naturalNumbers
.subscribeOn(Schedulers.newThread())
.subscribe(second);
final Subscription subscribe3 = naturalNumbers
.subscribeOn(Schedulers.newThread())
.subscribe(third);
Thread.sleep(1000);
System.out.println("Unsubscribing");
subscribe1.unsubscribe();
subscribe2.unsubscribe();
subscribe3.unsubscribe();
Thread.sleep(1000);
System.out.println("Stopping");
Observable.Generate is exactly the operator to solve this class of problem reactively. I also assume this is a pedagogical example, since using an iterable for this is probably better anyway.
Your code produces the whole stream on the subscriber's thread. Since it is an infinite stream the subscribe call will never complete. Aside from that obvious problem, unsubscribing is also going to be problematic since you aren't checking for it in your loop.
You want to use a scheduler to solve this problem - certainly do not use subscribeOn since that would burden all observers. Schedule the delivery of each number to onNext - and as a last step in each scheduled action, schedule the next one.
Essentially this is what Observable.generate gives you - each iteration is scheduled on the provided scheduler (which defaults to one that introduces concurrency if you don't specify it). Scheduler operations can be cancelled and avoid thread starvation.
Rx.NET solves it like this (actually there is an async/await model that's better, but not available in Java afaik):
static IObservable<int> Range(int start, int count, IScheduler scheduler)
{
return Observable.Create<int>(observer =>
{
return scheduler.Schedule(0, (i, self) =>
{
if (i < count)
{
Console.WriteLine("Iteration {0}", i);
observer.OnNext(start + i);
self(i + 1);
}
else
{
observer.OnCompleted();
}
});
});
}
Two things to note here:
The call to Schedule returns a subscription handle that is passed back to the observer
The Schedule is recursive - the self parameter is a reference to the scheduler used to call the next iteration. This allows for unsubscription to cancel the operation.
Not sure how this looks in RxJava, but the idea should be the same. Again, Observable.generate will probably be simpler for you as it was designed to take care of this scenario.
When creating infinite sequencies care should be taken to:
subscribe and observe on different threads; otherwise you will only serve single subscriber
stop generating values as soon as subscription terminates; otherwise runaway loops will eat your CPU
The first issue is solved by using subscribeOn(), observeOn() and various schedulers.
The second issue is best solved by using library provided methods Observable.generate() or Observable.fromIterable(). They do proper checking.
Check this:
Observable<Integer> naturalNumbers =
Observable.<Integer, Integer>generate(() -> 1, (s, g) -> {
logger.info("generating {}", s);
g.onNext(s);
return s + 1;
}).subscribeOn(Schedulers.newThread());
Disposable sub1 = naturalNumbers
.subscribe(v -> logger.info("1 got {}", v));
Disposable sub2 = naturalNumbers
.subscribe(v -> logger.info("2 got {}", v));
Disposable sub3 = naturalNumbers
.subscribe(v -> logger.info("3 got {}", v));
Thread.sleep(100);
logger.info("unsubscribing...");
sub1.dispose();
sub2.dispose();
sub3.dispose();
Thread.sleep(1000);
logger.info("done");

Categories

Resources