I have following code:
public final class Start {
private static final CountDownLatch FINAL_THREAD = new CountDownLatch(1);
private static String getValue() {
System.out.println("Waiting...");
try {
Thread.sleep(Duration.ofSeconds(1).toMillis());
return "value";
} catch (InterruptedException e) {
return "interrupted";
}
}
private static void whenComplete(String value, Throwable ex) {
if (ex != null) {
System.out.println("whenComplete Ex: " + ex);
} else {
System.out.println("whenComplete Value: " + value);
}
}
private static String handle(String value, Throwable ex) {
if (ex != null) {
System.out.println("handle Ex: " + ex);
} else {
System.out.println("handle Value: " + value);
}
FINAL_THREAD.countDown();
return value;
}
private static String peek(String value) {
System.out.println("peek: " + value);
return value;
}
private static CompletableFuture<String> createRequest() {
System.out.println("Create....");
return CompletableFuture.supplyAsync(Start::getValue)
.thenApply(Start::peek)
.handle(Start::handle)
.whenComplete(Start::whenComplete);
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
createRequest().completeExceptionally(new RuntimeException("TEST"));
FINAL_THREAD.await();
}
}
When I execute it I get output like this:
> Task :Start.main()
Create....
Waiting...
peek: value
handle Value: value
BUILD SUCCESSFUL in 10s
I don't understand why Start::whenComplete is not called when both Start::peek and Start::handle are. If I switch handle with whenComplete then Start::handle will not be called, but Start::whenComplete will. I would expect that Start::whenComplete will be called with RuntimeExeception in this case, while other stages will be executed with value provided by Start::getValue.
I think the documentation of CompletableFuture covers this, but let's slowly get to it, as it is not that trivial. First we need to refactor slightly your code:
private static CompletableFuture<String> createRequest() {
System.out.println("Create....");
CompletableFuture<String> one = CompletableFuture.supplyAsync(Start::getValue);
CompletableFuture<String> two = one.thenApply(Start::peek);
CompletableFuture<String> three = two.handle(Start::handle);
CompletableFuture<String> four = three.whenComplete(Start::whenComplete);
return four;
}
And let's slightly change your main too:
public static void main(String[] args) {
CompletableFuture<String> f = createRequest();
boolean didI = f.completeExceptionally(new RuntimeException("TEST"));
System.out.println("have I completed it? : " + didI);
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5));
}
Now let's carefully looks at this:
CompletableFuture<String> four = three.whenComplete(Start::whenComplete);
via the documentation of whenComplete:
Returns a new CompletionStage with the same result or exception as this stage, that executes the given action when this stage completes.
breaking it into smaller pieces:
Returns a new CompletionStage (four) with the same result or exception as this stage (three), that executes the given action (Start::whenComplete) when this stage (three) completes.
Who is supposed to execute Start::whenComplete? According to the documentation : four. When is it supposed to execute it? When three is completed.
According to your flow, before three is completed, you completeExceptionally your four. So when three is done, so is four - meaning it can't execute that Start::whenComplete (action); simply because it is already completed. Another way to think about it is that when your code reaches this line:
CompletableFuture<String> four = three.whenComplete(Start::whenComplete);
four is an un-completed future. It can be completed in two ways:
either when three is completed, thus triggering Start::whenComplete
externally (what you do with completeExceptionally)
Because you complete it externally before three is completed, it will not run that action.
If you chain an action to the future that you complete:
four.whenComplete(Start::whenComplete);
this is when you will see the desired output.
Related
I have an async chain in my java code that i want to stop after a certain timeout
so i created a threadPool with some threads and called the CompletableFuture like this
ExecutorService pool = Executors.newFixedThreadPool(10);
than i have a cyclic method that loads data from the db and executes some task on it, once all the CompletableFutures are completed its doing it again
CompletableFuture<MyObject> futureTask =
CompletableFuture.supplyAsync(() -> candidate, pool)
.thenApply(Task1::doWork).thenApply(Task2::doWork).thenApply(Task3::doWork)
.thenApply(Task4::doWork).thenApply(Task5::doWork).orTimeout(30,TimeUnit.SECONDS)
.thenApply(Task6::doWork).orTimeout(30,TimeUnit.SECONDS)
.exceptionally(ExceptionHandlerService::handle);
My problem is in task6, that has a very intensive task (its a network connection task that sometimes hangs forever)
i noticed that my orTimeout is being fired correctly after 30 seconds, but the thread running Task6 is still being running
after few cycles like this, all my threads are drained and my app dies
How can i cancel the running threads on the pool after the timeout has reached?
(without calling pool.shutdown())
UPDATE*
inside the main thread i did a simple check as shown here
for (int i = TIME_OUT_SECONDS; i >= 0; i--) {
unfinishedTasks = handleFutureTasks(unfinishedTasks, totalBatchSize);
if(unfinishedTasks.isEmpty()) {
break;
}
if(i==0) {
//handle cancelation of the tasks
for(CompletableFuture<ComplianceCandidate> task: unfinishedTasks) {
**task.cancel(true);**
log.error("Reached timeout on task, is canceled: {}", task.isCancelled());
}
break;
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception ex) {
}
}
What i see is that after few cycles, all the tasks complain about timeout...
in the first 1-2 cycles, i still get epected responses (while there are threads to process it)
i still feel that the thread pool is exhausted
I know you said without calling pool.shutDown, but there is simply no other way. When you look at your stages though, they will run in either the thread that "appends" them (adding those thenApply) or a thread from that pool that you define. May be an example should make more sense.
public class SO64743332 {
static ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> dbCall(), pool);
//simulateWork(4);
CompletableFuture<String> f2 = f1.thenApply(x -> {
System.out.println(Thread.currentThread().getName());
return transformationOne(x);
});
CompletableFuture<String> f3 = f2.thenApply(x -> {
System.out.println(Thread.currentThread().getName());
return transformationTwo(x);
});
f3.join();
}
private static String dbCall() {
simulateWork(2);
return "a";
}
private static String transformationOne(String input) {
return input + "b";
}
private static String transformationTwo(String input) {
return input + "b";
}
private static void simulateWork(int seconds) {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(seconds));
} catch (InterruptedException e) {
System.out.println("Interrupted!");
e.printStackTrace();
}
}
}
They key point of the above code is this : simulateWork(4);. Run the code with it commented out and then uncomment it. See what thread is actually going to execute all those thenApply. It is either main or the same thread from the pool, meaning although you have a pool defined - it's only a single thread from that pool that will execute all those stages.
In this context, you could define a single thread executor (inside a method let's say) that will run all those stages. This way you could control when to call shutDownNow and potentially interrupt (if your code responds to interrupts) the running task. Here is a made-up example that simulates that:
public class SO64743332 {
public static void main(String[] args) {
execute();
}
public static void execute() {
ExecutorService pool = Executors.newSingleThreadExecutor();
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> dbCall(), pool);
CompletableFuture<String> cf2 = cf1.thenApply(x -> transformationOne(x));
// give enough time for transformationOne to start, but not finish
simulateWork(2);
try {
CompletableFuture<String> cf3 = cf2.thenApply(x -> transformationTwo(x))
.orTimeout(4, TimeUnit.SECONDS);
cf3.get(10, TimeUnit.SECONDS);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
pool.shutdownNow();
}
}
private static String dbCall() {
System.out.println("Started DB call");
simulateWork(1);
System.out.println("Done with DB call");
return "a";
}
private static String transformationOne(String input) {
System.out.println("Started work");
simulateWork(10);
System.out.println("Done work");
return input + "b";
}
private static String transformationTwo(String input) {
System.out.println("Started transformation two");
return input + "b";
}
private static void simulateWork(int seconds) {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(seconds));
} catch (InterruptedException e) {
System.out.println("Interrupted!");
e.printStackTrace();
}
}
}
Running this you should notice that transformationOne starts, but it is interrupted because of the shutDownNow.
The drawback of this should be obvious, every invocation of execute will create a new thread pool...
I have this function here:
Function<Integer, Integer> func = (value) -> value + 5;
func = func.andThen((value) -> {
//Imagine that here some code executed and raised an exception, I'm throwing it
//manually just for the sake of this example.
throw new RuntimeException("failed");
});
func = func.andThen((value) -> {
System.out.println("Reached last function !");
return value;
});
executeFunction(func);
Now, you can see that I am throwing a Runtime exception in the first andThen method. That is because I want to prevent the second andThen to be executed. Is that the best way to do it?
Also, I notice that if I execute this function inside a different thread (async) the exception is not printed in my console, and I want to know that the exception happened.
private static void executeFunction(Function<Integer, Integer> function) {
CompletableFuture.supplyAsync(() -> function.apply(100));
}
In this case, if I want to make sure that the exception gets logged, but that the next function in the andThen chain doesn't get executed, should I log and throw? Isn't it an ati-pattern?
Instantiating and throwing lots of exceptions can become quite expensive, which is why they're supposed to be limited to exceptional circumstances. Instead, you can use Optional for control flow:
func = (value) -> Optional.of(value + 5);
func = func.andThen((optionalValue) -> {
// Instead of throwing an exception, return an empty Optional
System.out.println("Log the failure");
return Optional.empty();
});
func = func.andThen((optionalValue) -> {
optionalValue.map((value) -> { // This lambda will only execute if optionalValue is not empty
System.out.println("Reached last function !");
return value; // map wraps this in an Optional
});
});
// Finally, unwrap the value. Optional provides a number of ways to do this, depending on how you want to handle failure/empty
func = func.andThen((optional) -> optional.orElse(...));
executeFunction(func);
You can write a wrapper for functions/runnables, that logs and quits when your task fails. Like so:
class Runnables
{
public static Runnable trying(Runnable... runnables)
{
return () ->
{
int successes = 0;
try
{
for(Runnable runnable : runnables)
{
runnable.run();
successes++;
}
}
catch(Throwable t)
{
logger.error("Exception thrown from "+successes+"th runnable: ",t);
}
};
}
}
Then:
private static void executeFunction(Runnable... runnables)
{
CompletableFuture.supplyAsync(Runnables.trying(runnables));
}
You can get desired behavior by using CompletableFuture.thenApply method. For example:
public class Answer {
public static void main(String[] args) {
Function<Integer, Integer> fn0 = v -> v + 5;
Function<Integer, Integer> fn1 = v -> {
throw new RuntimeException("failed");
};
Function<Integer, Integer> fn2 = v -> {
System.out.println("Reached last function !");
return v;
};
CompletableFuture.supplyAsync(() -> fn0.apply(100))
.thenApply(fn1)
.thenApply(fn2)
.exceptionally(throwable -> {
// next line prints the exception thrown by fn1, wrapped in java.util.concurrent.CompletionException
System.out.println("Failed with error: " + throwable);
return 0; // default value, used when exception is thrown
});
}
}
Basically, CompletableFuture chain will be interrupted by exception "out of the box", so no additional handling is required.
Alternatively, if you want a bit more general approach:
public class Answer {
public static void main(String[] args) {
executeAsync(() -> stepOne(100))
.thenApply(Answer::stepTwo)
.thenApply(Answer::finalStep)
.exceptionally(Answer::handleException);
}
private static CompletableFuture<Integer> executeAsync(Supplier<Integer> task) {
return CompletableFuture.supplyAsync(task::get);
}
private static Integer stepOne(Integer value) {
return value + 5;
}
private static Integer stepTwo(Integer value) {
throw new RuntimeException("failed");
}
private static Integer finalStep(Integer value) {
System.out.println("Reached last function !");
return value;
}
private static Integer handleException(Throwable throwable) {
// next line prints the exception thrown by any step before, wrapped in java.util.concurrent.CompletionException
System.out.println("Failed with error: " + throwable);
return 0; // default value
}
Notes:
Using thenApply you can chain as many function calls as you need
In the last example methods inside same class can be replaced by methods from other classes (not necessarily static ones)
I have stupid problem with RxJava2.
I need to run two long operations at the same time. I know that I should use Observable.zip() and I use it.
The problem, that my long operations is run one after another and another problem that my long operations starting before I subscribe to them.
Let's imagine that this is my long operation that I should run async.
private String doSomethingLong() {
Random rand = new Random();
int value = rand.nextInt(5);
Timber.i("Do something for [%d] sec [%s]", value, Thread.currentThread().getName());
try {
Thread.sleep(value * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
return String.format(Locale.getDefault(), "Exception [%s]", e.getMessage());
}
return String.format(Locale.getDefault(),"Job for [%d] seconds", value);
}
And let there is a method like test() that will try to make it parallel:
public void test() {
final long started = System.currentTimeMillis();
Observable<String> just1 = Observable.just(doSomethingLong()).subscribeOn(Schedulers.newThread());
Observable<String> just2 = Observable.just(doSomethingLong()).subscribeOn(Schedulers.newThread());
Observable.zip(just1, just2, new Func2<String, String, Combined>() {
#Override
public Combined call(String s, String s2) {
return new Combined(s, s2);
}
}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Combined>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(Combined combined) {
long total = System.currentTimeMillis() - started;
Timber.i("TOTAL [%d]ms [%s]", total, combined.toString());
}
});
}
When I'm trying to run this I observe that two observables just1 and just2 runs one after another... And it's confused me...
But there is another staff that confused me more... I commented Observable.zip and noticed that just1 and just2 started method doSomethingLong() before I subscribed to them...
Let me show:
public void test() {
final long started = System.currentTimeMillis();
Observable<String> just1 = Observable.just(doSomethingLong()).subscribeOn(Schedulers.newThread());
Observable<String> just2 = Observable.just(doSomethingLong()).subscribeOn(Schedulers.newThread());
// Observable.zip(just1, just2, new Func2<String, String, Combined>() {
// #Override
// public Combined call(String s, String s2) {
// return new Combined(s, s2);
// }
// }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Combined>() {
// #Override
// public void onCompleted() {
//
// }
//
// #Override
// public void onError(Throwable e) {
//
// }
//
// #Override
// public void onNext(Combined combined) {
// long total = System.currentTimeMillis() - started;
// Timber.i("TOTAL [%d]ms [%s]", total, combined.toString());
// }
// });
}
This code make almost same - it's run two times doSomethingLong() one after another...
What I'm expect:
1. I need that doSomethingLong() methods run parallel
2. I'm asking to explain why those methods runs before I start subscribe them.
3. How should I write me code well in this situation. I want that doSomethingLong() methods do not called before I subscribe to them.
Thanks a lot. Hope that I explain problem well.
Observable.just doesn't run anything when you subscribe. It emits the elements when you subscribe, but your doSomethingLong will run as soon as you pass it as an argument. That's normal and it's how the language works.
What you're looking for is a way to say return this when we subscribe, but also only run it at that time and hopefully on a background thread.
There are a couple of answers for this, here are some:
Using defer
There's an operator called defer which takes a lambda which will be executed once you subscribe:
Observable.defer(() -> doSomethingLong())
This will only execute doSomethingLong when you subscribe
Using fromCallable
You can create an observable from a lambda. This is known as fromCallable:
Observable.fromCallable(() -> doSomethingLong())
Similarly, this will only run doSomethingLong when you subscribe
Using create
I think this is perhaps the most discouraged way of doing it, since there's a couple of things you have to deal with, but I think for the she of completeness it's ok to mention:
Observable.create( emitter -> {
if(emitter.isDisposed()) return;
emitter.onNext(doSomethingLong());
emitter.onComplete();
});
Again, I'm sure there's more ways of doing this. I just wanted to explain the issue and give some options.
Create your Observables as Observable.fromCallable{}.
And instead of zip use combineLatest()
Docs:
http://reactivex.io/RxJava/javadoc/io/reactivex/Observable.html#fromCallable-java.util.concurrent.Callable-
http://reactivex.io/documentation/operators/combinelatest.html
I have an application where by clicking buttons (that number is defined) user creates tasks (Callable) that do some calculations. I want to be able to react when the task is finished. Using Future.get() blocks the application. Is there any way to be able to react when the Callable returns the result?
private static void startTask(int i){
try{
Future<Integer> future = executor.submit(callables.get(i-1));
ongoingTasks.put(i, future);
awaitResult(future, i);
}
catch(Exception e){
e.printStackTrace();
}
}
private static void awaitResult(Future<?> future, int taskNo) throws InterruptedException, ExecutionException{
System.out.println("result : " + future.get());
JButton b = buttons.get(taskNo);
b.setEnabled(false);
}
It sounds like you want a CompletableFuture. You have a function which is a "supplier" which supplies a value. This is the function that's actually doing the work.
You then have a function which accepts that value whenever the worker is done.
This is all asynchronous, so everything else carries on regardless of the outcome.
class Main
{
private static Integer work() {
System.out.println("work");
return 3;
}
private static void done(Integer i) {
System.out.println("done " + i);
}
public static void main (String... args)
{
CompletableFuture.supplyAsync(Main::work)
.thenAccept(Main::done);
System.out.println("end of main");
}
}
Sample output:
end of main
work
done 3
Suppose something like the following:
public boolean doThisThing(SomeArg arg) {
if(iAmAllowedToDoIt()) {
doThing(arg);
return true;
} else {
return false;
}
Suppose that iAmAllowedToDoIt() is a very expensive method, and doThisThing() is invoked by many threads concurrently, and I am allowed to do everything given that I am allowed to do anything, is there a way to batch invocations of iAmAllowedToDoIt() such that I would accumulate SomeArgs in a concurrent data structure, and invoke doThing on all of them at once after resolving iAmAllowedToDoIt only one time without modifying the API? What would that code look like? I can't figure out how to do multithreaded batching performantly like this without modifying the API. An ideal answer would include something that doesn't rely on blocking for a fixed period of time to accumulate invocations of doThisThing().
Ideally it would end up as something like:
Call doThisThing
Call iAmAllowedToDoIt asynchronously
All calls to doThisThing before (2) retuns block until (2) returns
(2) Returns, if true invoke doThing for all blocked doThisThing()s
Your containing object could have an AtomicReference that holds a CompleteableFuture for the computation of iAmAllowedToDoIt(). Additional invocations of doThisThing() simply await the completion of the completable future if one is present or create a new one otherwise, with an appropriate CAS loop to avoid creating more than one instance at a time.
Upon completion the reference is set to null again so that threads invoking the method at a later point can start a new computation.
You could do the following (which implements an algorithm similar to the one proposed by #the8472) :
public class Test {
/**
* Lock used to guard accesses to allowedFuture
*/
private final Object lock = new Object();
/**
* The future result being computed, reset to null as soon as the result is known
*/
private FutureTask<Boolean> allowedFuture = null;
private static final Random RANDOM = new Random();
public boolean doThisThing() throws ExecutionException, InterruptedException {
if (iAmAllowedToDoIt()) {
System.out.println("doing it...");
return true;
}
else {
System.out.println("not doing it...");
return false;
}
}
private boolean iAmAllowedToDoIt() throws ExecutionException, InterruptedException {
// if true, this means that this thread is the one which must really compute if I am allowed
boolean mustCompute = false;
// The Future holding the result which is either the cached one, or a new one stored in the cache
FutureTask<Boolean> result;
synchronized (lock) {
// if no one has computed the result yet, or if it has been computed and thus must be recomputed
// then create it
if (this.allowedFuture == null) {
mustCompute = true;
this.allowedFuture = new FutureTask<>(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
System.out.println("computing if I am allowed...");
Thread.sleep(RANDOM.nextInt(3000));
boolean allowed = RANDOM.nextBoolean();
System.out.println(allowed ? "allowed!" : "not allowed!");
return allowed;
}
});
}
result = this.allowedFuture;
}
if (mustCompute) {
allowedFuture.run();
// reset the cache to null, so that the next thread recomputes the result
synchronized (lock) {
this.allowedFuture = null;
}
}
return result.get();
}
public static void main(String[] args) {
Test test = new Test();
Runnable r = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(RANDOM.nextInt(6000));
test.doThisThing();
}
catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}
};
for (int i = 0; i < 50; i++) {
Thread t = new Thread(r);
t.start();
}
}
}