I've inherited some code and there is nobody of the original developers left. The code uses heavily CompletableFuture, and it's the first time I use it, so I'm still trying to wrap my head around it. As I understand it, a (Completable)Future is typically used with some multithreading mechanism that will allow us to do some other thing while a time consuming task is executing, and then simply fetch its result via the Future. As in the javadoc:
interface ArchiveSearcher { String search(String target); }
class App {
ExecutorService executor = ...
ArchiveSearcher searcher = ...
void showSearch(final String target) throws InterruptedException {
Future<String> future = executor.submit(new Callable<String>() {
public String call() {
return searcher.search(target);
}});
displayOtherThings(); // do other things while searching
try {
displayText(future.get()); // use future
} catch (ExecutionException ex) { cleanup(); return; }
}
}
However, in this application that I've inherited, the following pattern that doesn't use any multithreading appears a bunch of times:
public Object serve(Object input) throws ExecutionException, InterruptedException {
CompletableFuture<Object> result = delegate1(input);
return result.get();
}
private CompletableFuture<Object> delegate1(Object input) {
// Do things
return delegate2(input);
}
private CompletableFuture<Object> delegate2(Object input) {
return CompletableFuture.completedFuture(new Object());
}
To me, this is equivalent to:
public Object serve(Object input) {
Object result = delegate1(input);
return result;
}
private Object delegate1(Object input) {
// Do things
return delegate2(input);
}
private Object delegate2(Object input) {
return new Object();
}
Of course the code is much more complex, and returns exceptionallyCompletedFuture in case of error, but there are is Callable, no Runnable, no Executor, no supplyAsync() no sign of multithreading. What am I missing? What's the point of using a Future in a singled-threaded context?
Futures are critical for situations where there is asynchronous programming. One of the biggest advantages of asynchronous programming is it allows you to write very efficient code with a single thread.
Furthermore, futures tend to be an all-or-nothing proposition. If you want to write asynchronous code you have to do so from top to bottom, even if not every method does something asynchronous.
For example, consider you want to write a single threaded HTTP server like twisted or express. The top level of your server (very liberal pseudocode here) might look something like:
while (true) {
if (serverSocket.ready()) {
connection = serverSocket.accept();
futures.add(server.serve(connection));
}
for (Future future : futures) {
if (future.isDone()) {
Object result = future.get();
sendResult(result);
}
}
//Some kind of select-style wait here
}
There is only one thread but any time an operation happens that would normally require a wait (reading from database, file, reading in the request, etc.) it uses futures and doesn't block the one thread so you have a highly performant single threaded HTTP server.
Now, imagine what would happen if the highest level of your application was like the above and at some point some request at a very low level had to read something from a file. That file read would generate a future. If all of your middle layers in between didn't handle futures then you would have to block and it would defeat the purpose. This is why I say futures tend to be all-or-nothing.
So my guess is either:
Your friend does something asynchronous currently and you haven't caught it yet (does he ever read from a file or database or anything? If so, is he blocking?).
He was planning on someday doing something asynchronous and wanted to plan for it.
He spent a lot of time in other asynchronous frameworks and grew to like the style even if he isn't using it correctly.
Yes, for now there is no multithreading used in that code. Looks like there was an intention to write single-threaded code in such a way that if developer later decides to use multithreading then only
delegate2()
method should be modified.
ExecutorService implementations typically manage threads. I've used the ThreadPoolExecutor, which does exactly that. You commented out which ExecutorService your code uses.
The main point of asynchronous code is to defer the continuation code.
The most common scenario is I/O, where instead of waiting for an operation to finish, you say "do your thing and notify me when you're finished", or more commonly, "do your thing and do this when you're finished".
This doesn't imply threads at all. Reading from any device, be it a network card or a hard drive, usually has some sort of signal or interrupt sent from the device to the CPU. You could use the CPU in the meantime. The "notify me" is more common in lower-level code, where you implement a dispatching loop or scheduler; the "do this" is more common in higher-level code, where you use an established library or framework that dispatches and/or schedules for you.
Less common scenarios include deferring execution without blocking a thread (think of a timer versus Thread.sleep()) and splitting work. Actually, splitting work is very common with multiple threads, where you can improve performance with a bit of overhead, but not so much with a single thread, where the overhead is just, well, overhead.
The code you provide as an example that just builds completed CompletableFutures, whether successfully or exceptionally, is a part of the overhead of asynchronous code that isn't really asynchronous. That is, you must still follow a defined async style, which in this case requires a small amount of memory allocation for results, even if you can provide results immediately.
This may become noticeable on thousands of calls per second, or hundreds of calls per second per thread with dozens of threads.
Sometimes, you can optimize by having predefined completed futures for e.g. null, 0, 1, -1, an empty array/list/stream, or any other very common or even fixed result you may have specifically in your domain. A similar approach is to cache a wrapping future, not just the result, while the result remains the same. But I suggest you first profile before going this way, you may end up optimizing prematurely something that most probably is not a bottleneck.
Related
I am developing a Load Test application in Java for an Ethereum blockchain, using the web3j library. The specific functions used from this library, send transactions asynchronously, and return Future objects. That library provides many features which met all my needs initially for the application development. However, after designing and re-designing a load test application, I noticed an issue. I can only have N Futures deployed at once, where N is the number of available cores on my machine.
This is very inefficient since each transaction takes at least 10 seconds to integrate into the blockchain, and the Futures are continuously running in the background. If they are converted to RxJava observables (using the from() function of RxJava), will they still continuously run in the background to check if their data is available, or would I be able to overlay many checks at once. For example, if a check took 0.1 seconds and I needed each future to be checked once a second, then I could run 10 checks on one core instead of 1. If converting a Future to Observable will still exhibit the continuous-core-usage behavior, is there a different way to go about this that doesn't involve refactoring a lot of the web3j internal code?
The culprit may be this function, contained within the Async.java file. This function is called by internal web3j functions to send Transactions.
public static <T> CompletableFuture<T> run(Callable<T> callable) {
CompletableFuture<T> result = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
// we need to explicityly catch any exceptions,
// otherwise they will be silently discarded
try {
result.complete(callable.call());
} catch (Throwable e) {
result.completeExceptionally(e);
}
});
return result;
}
First of all, if you expect your task to return a result, you should use supplyAsync rather than runAsync.
But onto the more substantive part of your question, when you call runAsync or supplyAsync with only the task to be run, it will run on the JVM-wide ForkJoinPool, which as you have guessed has as many threads available to it as has cores on your machine. You can, however, also supply an ExecutorService of your choice, which may have more threads than cores.
ExecutorService executor = Executors.newFixedThreadPool(NUM_DESIRED_THREADS);
CompletableFuture<T> result = CompletableFuture.supplyAsync(callable, executor);
The above code will allow as many as NUM_DESIRED_THREADS tasks to run concurrently.
I would like to know the difference between
CompletableFuture,Future and Observable RxJava.
What I know is all are asynchronous but
Future.get() blocks the thread
CompletableFuture gives the callback methods
RxJava Observable --- similar to CompletableFuture with other benefits(not sure)
For example: if client needs to make multiple service calls and when we use Futures (Java) Future.get() will be executed sequentially...would like to know how its better in RxJava..
And the documentation http://reactivex.io/intro.html says
It is difficult to use Futures to optimally compose conditional asynchronous execution flows (or impossible, since latencies of each request vary at runtime). This can be done, of course, but it quickly becomes complicated (and thus error-prone) or it prematurely blocks on Future.get(), which eliminates the benefit of asynchronous execution.
Really interested to know how RxJava solves this problem. I found it difficult to understand from the documentation.
Futures
Futures were introduced in Java 5 (2004). They're basically placeholders for a result of an operation that hasn't finished yet. Once the operation finishes, the Future will contain that result. For example, an operation can be a Runnable or Callable instance that is submitted to an ExecutorService. The submitter of the operation can use the Future object to check whether the operation isDone(), or wait for it to finish using the blocking get() method.
Example:
/**
* A task that sleeps for a second, then returns 1
**/
public static class MyCallable implements Callable<Integer> {
#Override
public Integer call() throws Exception {
Thread.sleep(1000);
return 1;
}
}
public static void main(String[] args) throws Exception{
ExecutorService exec = Executors.newSingleThreadExecutor();
Future<Integer> f = exec.submit(new MyCallable());
System.out.println(f.isDone()); //False
System.out.println(f.get()); //Waits until the task is done, then prints 1
}
CompletableFutures
CompletableFutures were introduced in Java 8 (2014). They are in fact an evolution of regular Futures, inspired by Google's Listenable Futures, part of the Guava library. They are Futures that also allow you to string tasks together in a chain. You can use them to tell some worker thread to "go do some task X, and when you're done, go do this other thing using the result of X". Using CompletableFutures, you can do something with the result of the operation without actually blocking a thread to wait for the result. Here's a simple example:
/**
* A supplier that sleeps for a second, and then returns one
**/
public static class MySupplier implements Supplier<Integer> {
#Override
public Integer get() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//Do nothing
}
return 1;
}
}
/**
* A (pure) function that adds one to a given Integer
**/
public static class PlusOne implements Function<Integer, Integer> {
#Override
public Integer apply(Integer x) {
return x + 1;
}
}
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newSingleThreadExecutor();
CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new MySupplier(), exec);
System.out.println(f.isDone()); // False
CompletableFuture<Integer> f2 = f.thenApply(new PlusOne());
System.out.println(f2.get()); // Waits until the "calculation" is done, then prints 2
}
RxJava
RxJava is whole library for reactive programming created at Netflix. At a glance, it will appear to be similar to Java 8's streams. It is, except it's much more powerful.
Similarly to Futures, RxJava can be used to string together a bunch of synchronous or asynchronous actions to create a processing pipeline. Unlike Futures, which are single-use, RxJava works on streams of zero or more items. Including never-ending streams with an infinite number of items. It's also much more flexible and powerful thanks to an unbelievably rich set of operators.
Unlike Java 8's streams, RxJava also has a backpressure mechanism, which allows it to handle cases in which different parts of your processing pipeline operate in different threads, at different rates.
The downside of RxJava is that despite the solid documentation, it is a challenging library to learn due to the paradigm shift involved. Rx code can also be a nightmare to debug, especially if multiple threads are involved, and even worse - if backpressure is needed.
If you want to get into it, there's a whole page of various tutorials on the official website, plus the official documentation and Javadoc. You can also take a look at some of the videos such as this one which gives a brief intro into Rx and also talks about the differences between Rx and Futures.
Bonus: Java 9 Reactive Streams
Java 9's Reactive Streams aka Flow API are a set of Interfaces implemented by various reactive streams libraries such as RxJava 2, Akka Streams, and Vertx. They allow these reactive libraries to interconnect, while preserving the all important back-pressure.
I have been working with Rx Java since 0.9, now at 1.3.2 and soon migrating to 2.x I use this in a private project where I already work on for 8 years.
I wouldn't program without this library at all anymore. In the beginning I was skeptic but it is a complete other state of mind you need to create. Quiete difficult in the beginning. I sometimes was looking at the marbles for hours.. lol
It is just a matter of practice and really getting to know the flow (aka contract of observables and observer), once you get there, you'll hate to do it otherwise.
For me there is not really a downside on that library.
Use case:
I have a monitor view that contains 9 gauges (cpu, mem, network, etc...). When starting up the view, the view subscribes itselfs to a system monitor class that returns an observable (interval) that contains all the data for the 9 meters.
It will push each second a new result to the view (so not polling !!!).
That observable uses a flatmap to simultaneously (async!) fetch data from 9 different sources and zips the result into a new model your view will get on the onNext().
How the hell you gonna do that with futures, completables etc ... Good luck ! :)
Rx Java solves many issues in programming for me and makes in a way a lot easier...
Advantages:
Statelss !!! (important thing to mention, most important maybe)
Thread management out of the box
Build sequences that have their own lifecycle
Everything are observables so chaining is easy
Less code to write
Single jar on classpath (very lightweight)
Highly concurrent
No callback hell anymore
Subscriber based (tight contract between consumer and producer)
Backpressure strategies (circuit breaker a like)
Splendid error handling and recovering
Very nice documentation (marbles <3)
Complete control
Many more ...
Disadvantages:
- Hard to test
Java's Future is a placeholder to hold something that will be completed in the future with a blocking API. You'll have to use its' isDone() method to poll it periodically to check if that task is finished. Certainly you can implement your own asynchronous code to manage the polling logic. However, it incurs more boilerplate code and debug overhead.
Java's CompletableFuture is innovated by Scala's Future. It carries an internal callback method. Once it is finished, the callback method will be triggered and tell the thread that the downstream operation should be executed. That's why it has thenApply method to do further operation on the object wrapped in the CompletableFuture.
RxJava's Observable is an enhanced version of CompletableFuture. It allows you to handle the backpressure. In the thenApply method (and even with its brothers thenApplyAsync) we mentioned above, this situation might happen: the downstream method wants to call an external service that might become unavailable sometimes. In this case, the CompleteableFuture will fail completely and you will have to handle the error by yourself. However, Observable allows you to handle the backpressure and continue the execution once the external service to become available.
In addition, there is a similar interface of Observable: Flowable. They are designed for different purposes. Usually Flowable is dedicated to handle the cold and non-timed operations, while Observable is dedicated to handle the executions requiring instant responses. See the official documents here: https://github.com/ReactiveX/RxJava#backpressure
All three interfaces serve to transfer values from producer to consumer. Consumers can be of 2 kinds:
synchronous: consumer makes blocking call which returns when the value is ready
asynchronous: when the value is ready, a callback method of the consumer is called
Also, communication interfaces differ in other ways:
able to transfer single value of multiple values
if multiple values, backpressure can be supported or not
As a result:
Future transferes single value using synchronous interface
CompletableFuture transferes single value using both synchronous and asynchronous interfaces
Rx transferes multiple values using asynchronous interface with backpressure
Also, all these communication facilities support transferring exceptions. This is not always the case. For example, BlockingQueue does not.
The main advantage of CompletableFuture over normal Future is that CompletableFuture takes advantage of the extremely powerful stream API and gives you callback handlers to chain your tasks, which is absolutely absent if you use normal Future. That along with providing asynchronous architecture, CompletableFuture is the way to go for handling computation heavy map-reduce tasks, without worrying much about application performance.
At one point in my application, I need to ask a cache (a HashMap, i.e.) for a value. If the value does not exist, I need to wait a little and try again. At the moment, this is implemented like this:
String result = cache.get(key);
for (int i = 0; result == null; i++) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
}
result = cache.get(key);
}
While it works, I have a feeling that using Thread.sleep is kinda false. Does the JDK provide anything for this sort of task? I thought about using an ScheduledExecutorService, but the thing is that it has to run in the main thread.
I would argue that your design is fundamentally problematic. Locking and memory visibility issues notwithstanding, you are essentially polling for an event using high level code. This is neither efficient nor very responsive w.r.t. latency.
You should switch to a more event-driven approach. At the very least, use an object monitor or a lock to wait for that value to be set, rather than polling.
Even better, use a message bus to register handlers and process events as they come - you can easily construct a multithreaded message bus using any BlockingQueue implementation to pass message objects.
Try using the BlockingQueue as a cache.
I don't think there is anyway around Thread.sleep if you really have to execute on the main thread.
Other possibility is using Object.wait(). It is almost like Thread.sleep() for you but supports interrupting by calling notify() on the same monitor.
Other possibility for you is to user java.util.Timer= (as was already mentioned by #Hovercraft Full Of Eels)
You could use a self populating cache(guava LoadingCache), so the get(...) will block until the data is fetched.
Combine it with a ExecutorService -> Future#get(long timeout, TimeUnit unit) And you could have timeouts too.
Hope i pointed you into the right direction :)
I have a critical section of my (Java) code which basically goes like the snippet below. They're coming in from a nio server.
void messageReceived(User user, Message message) {
synchronized(entryLock) {
userRegistry.updateLastMessageReceived(user,time());
server.receive(user,message);
}
}
However, a high percentage of my messages are not going to change the server state, really. They're merely the client saying "hello, I'm still here". I really don't want to have to make that inside the synchronization block.
I could use a synchronous map or something like that, but it's still going to incur a synchronization penalty.
What I would really like to do is to have something like a drop box, like this
void messageReceived(User user, Message message) {
dropbox.add(new UserReceived(user,time());
if(message.getType() != message.TYPE_KEPT_ALIVE) {
synchronized(entryLock) {
server.receive(user,message);
}
}
}
I have a cleanup routine to automatically put clients that aren't active to sleep. So instead of synchronizing on every kept alive message to update the registry, the cleanup routine can simply compile the kept alive messages in a single synchronization block.
So naturally, reconigizing a need for this, the first thing I did was start making a solution. Then I decided this was a non-trivial class, and a problem that was more than likely fairly common. so here I am.
tl;dr Is there a Java library or other solution I can use to facilitate atomically adding to a list of objects in an asynchronous manner? Collecting from the list in an asychronous manner is not required. I just don't want to synchronize on every add to the list.
ConcurrentLinkedQueue claims to be:
This implementation employs an efficient "wait-free" algorithm based on one described in Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms by Maged M. Michael and Michael L. Scott.
I'm not sure what the quotes on "wait-free" entail but the Concurrent* classes are good places to look for structures like you're looking for.
You might also be interested in the following: Effective Concurrency: Lock-Free Code — A False Sense of Security. It talks about how hard these things are to get right, even for experts.
Well, there are few things you must bear in mind.
First, there is very little "synchronization cost" if there is little contention (more than one thread trying to enter the synchronized block at the same time).
Second, if there is contention, you're going to incur some cost no matter what technique you're using. Paul is right about ConcurrentLinkedQueue and the "wait-free" means that thread concurrency control is not done using locks, but still, you will always pay some price for contention. You may also want to look at ConcurrentHashMap because I'm not sure a list is what you're looking for. Using both classes is quite simple and common.
If you want to be more adventurous, you might find some non-locking synchronization primitives in java.util.concurrent.atomic.
One thing we could do is to use a simple ArrayList for keep-alive messages:
Keep adding to this list whenever each keep-alive message comes.
The other thread would synch on a lock X and read and process
keep-alives. Note that this thread is not removing from list only
reading/copying.
Finally in messageReceived itself you check if the list has grown
say beyond 1000, in which case you synch on the lock X and clear the
list.
List keepAliveList = new ArrayList();
void messageReceived(User user, Message message) {
if(message.getType() == message.TYPE_KEPT_ALIVE) {
if(keepAliveList.size() > THRESHOLD) {
synchronized(X) {
processList.addAll(list);
list.clear();
}
}
keepAliveList.add(message);
}
}
//on another thread
void checkKeepAlives() {
synchronized(X) {
processList.addAll(list)
}
processKeepAlives(processList);
}
I notice that NetBeans is warning me about using Thread.sleep() in a while loop in my Java code, so I've done some research on the subject. It seems primarily the issue is one of performance, where your while condition may become true while the counter is still sleeping, thus wasting wall-clock time as you wait for the next iteration. This all makes perfect sense.
My application has a need to contact a remote system and periodically poll for the state of an operation, waiting until the operation is complete before sending the next request. At the moment the code logically does this:
String state = get state via RPC call
while (!state.equals("complete")) {
Thread.sleep(10000); // Wait 10 seconds
state = {update state via RPC call}
}
Given that the circumstance is checking a remote operation (which is a somewhat expensive process, in that it runs for several seconds), is this a valid use of Thread.sleep() in a while loop? Is there a better way to structure this logic? I've seen some examples where I could use a Timer class, but I fail to see the benefit, as it still seems to boil down to the same straightforward logic above, but with a lot more complexity thrown in.
Bear in mind that the remote system in this case is neither under my direct control, nor is it written in Java, so changing that end to be more "cooperative" in this scenario is not an option. My only option for updating my application's value for state is to create and send an XML message, receive a response, parse it, and then extract the piece of information I need.
Any suggestions or comments would be most welcome.
Unless your remote system can issue an event or otherwise notify you asynchronously, I don't think the above is at all unreasonable. You need to balance your sleep() time vs. the time/load that the RPC call makes, but I think that's the only issue and the above doesn't seem of concern at all.
Without being able to change the remote end to provide a "push" notification that it is done with its long-running process, that's about as well as you're going to be able to do. As long as the Thread.sleep time is long compared to the cost of polling, you should be OK.
You should (almost) never use sleep since its very inefficient and its not a good practice. Always use locks and condition variables where threads signal each other. See Mike Dahlin's Coding Standards for Programming with threads
A template is:
public class Foo{
private Lock lock;
private Condition c1;
private Condition c2;
public Foo()
{
lock = new SimpleLock();
c1 = lock.newCondition();
c2 = lock.newCondition();
...
}
public void doIt()
{
try{
lock.lock();
...
while(...){
c1.awaitUninterruptibly();
}
...
c2.signal();
}
finally{
lock.unlock();
}
}
}