Right now, I have a piece of code that contacts another server asking if an item is in a list, and returns a boolean value based on that returned value.
The code goes like so:
public boolean checkIfOnline(int accountId) {
//First loop is incase if someone is already checking. Second is for the checking that this account is doing.
while (isCheckingIfOnline) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
}
}
isCheckingIfOnline = true;
sendCheckIfOnline(accountId);
while (isCheckingIfOnline) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
}
}
return onlineResponse;
}
The onlineResponse and isCheckingIfOnline are changed within a method that handles what the other server returns, and this is the method I've thrown together to have the system wait for the other server to respond. Obviously, this is very flawed, as when this method gets called often, it'll slow down the system since it only allows for one query at a time, when it should allow for multiple queries to be executed simultaneously.
What other method could I use that accomplishes what the above code does, but allows for more than one query to run at once?
Edit: To clarify even more, checkIfOnline takes an account ID, and asks another server is that account ID is on a list, which that other server responds to the current server if the account ID is or is not on the list.
Sounds like you would want to make use of the ExecutorService in Java 6+.
The ExecutorService requires you to submit to it a class that implements Callable. When you submit a Callable to a ES, you receive back a Future that you can use to do a number of things, including cancelling the process or getting a result from a completed process.
It's a little hard for me to understand exactly what you are trying to achieve with your code and why you're threading that particular part. That being said, if you want to achieve concurrency there, you'd have to:
submit a Callable to the ES that does the online checks & query;
provide a way for the Callable to notify the your application that it has finished it's execution.
It will not be sufficient to simply submit the task and call Future.get() on it because whatever thread makes that call will be suspended until the task is completed.
You'd need to either allow the Callable to invoke a callback, or thread the class that performs the submission of the task and allow it to sit and wait for the future.get() method to return a result.
Good luck :)
Related
I am try to do something like
Optional<Order> orderDetails = orderRepository.findById(orderId);
if (orderDetails.isEmpty())
throw new OrderNotFoundException("Order not found!");
Optional<User> UserDetails = userRepository.findById(userId);
if (UserDetails.isEmpty())
throw new UserNotFoundException("User not found!");
List<OrderItem> ItemDetailsList = orderItemRepository.findByOrderIdOrderByItemIdAsc(orderId);
Where I want to call these three Services methods together in a non-blocking way, but I want to throw error if any one of those call fails and dont proceed furthur.
If all of the above works, then execute the later logic.
I am thinking of using allOff() then after that use get on the Futures and do the above logic of throwing error when the Optional is empty?
Is there better way of doing it ? i.e if one of them fails and others are still running, throw error and abort the other running tasks.
CompletableFuture is the wrong tool for the job here. And the main problem is that you want:
"...throw error and abort the other running tasks"
If you read what CompletableFuture::cancel documentation says, you will see that:
mayInterruptIfRunning – this value has no effect in this implementation because interrupts are not used to control processing.
So, even if you call cancel, this will not interrupt your tasks, they will still continue to completition. As such, your fundamental requirement can not be met.
There is a way with creating a custom pool of threads for that CompletableFuture that you want to cancel and shut down the pool, as an example here. But this is not trivial to do and your threads need to respond to interrupts properly.
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.
I would like to ask how I could implement sequential execution on methods depending on method's response.
Example:
public void processTicketing() throws TicketingException {
/** Process Steps 1-4 could throw TicketingException and does not have exact time of how long each methods will be processed.
* ? By default, is the sequence of process executions below followed from steps 1 to 4, Depending on how long each methods runs?
* If it is, then disregard this question on processes 1 to 4.
*/
processStep1();
processStep2();
processStep3();
processStep4();
for(int x=0; x < 10; x++){
//each call to this method should wait till the process is finish before calling the next one.
executeTicketCommand();
}
}
private void executeTicketCommand() throws TicketingException {
//NOTE:
//Send Request to a Web Service
//Web Service sends back a response with a status of the process
//The slower the internet, the slower the processing would be
//I want this method to finish first the processing, before being called again inside the calling loop.
if(hasError) throw new TicketingException("Error Processing Ticketing Command");
}
I am not sure whether to use synchronize or asynchronize for this scenario.
I am more concerned with the method execution of executeTicketCommand() since currently, they are invoked even if the previous executeTicketCommand() is not yet finished.
I am getting responses from the later executeTicketCommand() executions that I should wait for the current ticketing process to finish before I would start processing the next commands. This is something like lock the operation while it is still processing, after the processing... it can be run or called again.
This sample is just a representation to simplify the problem code as the real code is really complicated.
I am new to multithreading in java and would like to confirm that the following code works as I think it does.
// Inside class Menu
for (User user : users)
{
UserThread uT = new UserThread(user);
uT.start();
try
{
uT.join();
}
catch (InterruptedException e)
{
System.out.println(e.getMessage());
}
}
So for each user inside an arraylist called users, a new thread is created and started. Then uT.Join() is used to tell the Menu class to wait for the threads to finish before it can continue. Is that correct?
The multithreading works successfully without uT.Join() however the Menu class will display a menu and it will clash with the other threads that also print out something. Also without the join, the threads don't always print out in the same order, but when using join, they always seem to print in the same order, which is what is worrying me.
What I am unsure of is, does uT.Join() only ask the main thread that displays the menu to wait or does it also ask the other user threads to wait? I want my threads to be concurrent and not to obstruct each other in any way.
PS: I do realise there are multiple topics about this question and I apologise for adding another to the collection, but I was unable to find one that I could perfectly understand.
Thanks for reading, if I have missed any information that should be added please don't hesitate to inform me.
The way you designed the code is wrong. Using Thread#join will stop the execution of the current thread until the thead being executed finishes.
This is how the code should be designed:
List<UserThread> userThreadList = new ArrayList<UserThread>();
for (User user : users) {
UserThread uT = new UserThread(user);
uT.start();
userThreadList.add(uT);
}
for (UserThread uT : userThreadList) {
try
{
uT.join();
}
catch (InterruptedException e)
{
System.out.println(e.getMessage());
}
}
Note that it will be better to use ExecutorService for these tasks rather than trying to implement it manually.
Not quite, since your join is in the same loop as the the start, it will wait for the thread to finish before starting the next one.
You'd need two loops to accomplish that. One to start the threads and store them in some collection, and another loop to iterate through the collection and join each thread.
I'm trying to create a method that executes a given task in a maximum amount of time. If it fails to finish in that time, it should be retried a number of times before giving up. It should also wait a number of seconds between each try. Here's what I've come up with and I'd like some critiques on my approach. Is their a simpler way to do this using the ScheduledExecutorService or is my way of doing this suffice?
public static <T> T execute(Callable<T> task, int tries, int waitTimeSeconds, int timeout)
throws InterruptedException, TimeoutException, Exception {
Exception lastThrown = null;
for (int i = 0; i < tries; i++) {
try {
final Future<T> future = new FutureTask<T>(task);
return future.get(timeout, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
lastThrown = ex;
} catch (ExecutionException ex) {
lastThrown = (Exception) ex.getCause();
}
Thread.sleep(TimeUnit.SECONDS.toMillis(waitTimeSeconds));
}
if (lastThrown == null) {
lastThrown = new TimeoutException("Reached max tries without being caused by some exception. " + task.getClass());
}
throw lastThrown;
}
I think, but it's my opinion, that if you are scheduling network related tasks, you should not retry but eventually run them in parallel. I describe this other approach later.
Regarding your code, you should pass the task to an executor, or the FutureTask to a thread. It will not spawn a thread or execute by itself. If you have an executor (see ExecutorService), you don't even need a FutureTask, you can simply schedule it and obtain a callable.
So, given that you have an ExecutorService, you can call :
Future<T> future = yourExecutor.submit(task);
Future.get(timeout) will wait for that timeout and eventually return with TimeoutException even if the task has never started at all, for example if the Executor is already busy doing other work and cannot find a free thread. So, you could end up trying 5 times and waiting for seconds without ever giving the task a chance to run. This may or may not be what you expect, but usually it is not. Maybe you should wait for it to start before giving it a timeout.
Also, you should explicitly cancel the Future even if it throws TimeoutException, otherwise it may keep running, since nor documentation nor code says it will stop when a get with timeout fails.
Even if you cancel it, unless the Callable has been "properly written", it could keep running for some time. Nothing you can do it about it in this part of code, just keep in mind that no thread can "really stop" what another thread is doing in Java, and for good reasons.
However I suppose your tasks will mostly be network related, so it should react correctly to a thread interruption.
I usually use a different strategy is situations like this:
I would write public static T execute(Callable task, int maxTries, int timeout), so the task, max number of tries (potentially 1), max total timeout ("I want an answer in max 10 seconds, no matter how many times you try, 10 seconds or nothing")
I start spawning the task, giving it to an executor, and then call future.get(timeout/tries)
If I receive a result, return it. If I receive an exception, will try again (see later)
If however i get a timeout, I DON'T cancel the future, instead I save it in a list.
I check if too much time has passed, or too many retries. In that case I cancel all the futures in the list and throw exception, return null, whatever
Otherwise, I cycle, schedule the task again (in parallel with the first one).
See point 2
If I have not received a result, I check the future(s) in the list, maybe one of the previous spawned task managed to do it.
Assuming your tasks can be executed more than once (as I suppose they are, otherwise no way to retry), for network stuff I found this solution to work better.
Suppose your network is actually very busy, you ask for a network connection, giving 20 retries 2 seconds each. Since your network is busy, none of the 20 retries manages to get the connection in 2 seconds. However, a single execution lasting 40 seconds may manage to connect and receive data. It's like a person pressing f5 compulsively on a page when the net is slow, it will not do any good, since every time the browser has to start from the beginning.
Instead, I keep the various futures running, the first one that manages to get the data will return a result and the others will be stopped. If the first one hangs, the second one will work, or the third one maybe.
Comparing with a browser, is like opening another tab and retrying to load the page there without closing the first one. If the net is slow, the second one will take some time, but not stopping the first one, which will eventually load properly. If instead the first tab was hung, the second one will load rapidly. Whichever loads first, we can close the other tab.
The thread on which your execute is called will block for so much time. Not sure if this is correct for you. Basically , for these types of tasks , ScheduledExecutorService is best.You can schedule a task and specify the timings. Take a look at ScheduledThreadPoolExecutor