I'm learning about ExecutorService in a simple Spring Boot project. And I know that ExecutorService uses submit method to submit tasks and it will uses different threads for every task. And I don't understand where exactly are the new threads started. I know that a thread is started using method start. Can somebody explain me where is invoked the start method?
For example, this is my code:
try {
ExecutorService executorService = Executors.newFixedThreadPool(3);
Future<Accounts> accountFuture =
executorService.submit(
() -> accountsRepository.findByCustomerId(customer.getCustomerId()));
Future<List<Loans>> loansFuture =
executorService.submit(
() -> loansFeignClient.getLoansDetails(correlationId, customer));
Future<List<Cards>> cardsFuture =
executorService.submit(
() -> cardsFeignClient.getCardDetails(correlationId, customer));
executorService.shutdown();
Accounts account;
try {
executorService.awaitTermination(3, TimeUnit.SECONDS);
account = accountFuture.get();
} catch (ExecutionException | InterruptedException ex) {
logger.warn("Exception for accountFuture.get() = {}", ex);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
List<Loans> loansList = new ArrayList<>();
List<Cards> cardsList = new ArrayList<>();
try {
loansList.addAll(loansFuture.get());
} catch (ExecutionException | InterruptedException ex) {
logger.warn(ex.toString());
logger.warn("The call to GET loans details failed! Returning empty contactDetails body!");
}
try {
cardsList.addAll(cardsFuture.get());
} catch (ExecutionException | InterruptedException ex) {
logger.warn(ex.toString());
logger.warn("The call to GET cards details failed! Returning empty contactDetails body!");
}
...
Is the new thread started when the submit method is invoked or when the get method is invoked? And when is invoked the start method?
Thank you! Any feedback will be appreciated!
ExecutorService is another layer on top of Threads.
You dont have to manage the threads yourself, the ExecutorService is doing this for you.
Future<Accounts> accountFuture = executorService.submit(() -> accountsRepository.findByCustomerId(customer.getCustomerId()));
this is already starting a new thread. You get a future returned to tell you the state of the computation (if its finished, the result etc).
Under the hood the ExecutorService is doing the new Thread().start() things automatically.
Related
I have a problem with concurrent programming in Java. I am working on my bachelor thesis and I have to make several methods which will return me a String value. In the Futures TriggerMessageFututre and getMeterValuesFuture is a process running which takes between 1-5 seconds and returns a String Value when it's finished.
The problem is now that future.get() is blocking my main thread. I want to call the TriggerMessage and the getMeterValue methode in my main without blocking my main thread and get their answer as a return value when they are finished. I wasn't able to find a way to solve my problem, because either it was a solution without return value or it was a solution which blocked the thread.
private String TriggerMessage(String Messagetyp) throws InterruptedException, ExecutionException{
Future<String> future = new communicator().TriggerMessageFuture(queue,centralSystem,Messagetyp);
while(!future.isDone()) {
System.out.println("[TriggerMessage]: Calculating... ");
Thread.sleep(500);
}
String result = future.get(); //blocking
return result;
}
private String getMeterValue(String key) throws Exception{
Future<String> future = new communicator().getMeterValueFuture(queue,centralSystem,key);
while(!future.isDone()) {
System.out.println("[getMeterValue]: Calculating...");
Thread.sleep(500);
}
String result = future.get(); //blocking
return result;
}
It depends on what main thread are you referring to, plus if you can use CompletableFutures instead of plain old Java Futures.
Using the main(String[] args) thread
It's not possible to do it without any form of blocking. If you are not blocking on get, you'll have to block on a BlockingQueue implementation, otherwise the main thread just ends.
Using the Swing Event Dispatch thread
You'd need to submit a continuation task which is not possible with Future.get from the outside. So either you include this submission inside the task Future has been created for, or switch to CompletableFuture
ExecutorService exec = ...
Future<?> future = exec.submit(() -> {
var value = someCalculation();
SwingUtilities.invokeLater(() -> {
useValueOnEDT(value);
});
});
or
CompletableFuture<ValueType> cf = ...
cf.whenComplete((value, error) -> {
SwingUtilities.invokeLater(() -> {
if (error != null) {
handleErrorOnEdt(error);
} else {
useValueOnEDT(value);
}
});
});
Android Main Thread
The idea is the same as with Swing, but you'll have to use a Handler
// given value
new Handler(Looper.getMainLooper()).post(() -> {
useValueOnMainLooper(value);
});
You can wrap the Future into a CompletableFuture like so
static <T> CompletableFuture<T> from(Future<T> future) {
var delegate = new CompletableFuture<T>();
CompletableFuture.runAsync(() -> {
try {
delegate.complete(future.get());
} catch (Throwable e) {
delegate.completeExceptionally(e);
}
});
return delegate;
}
And then use that CompletableFuture to asynchronously handle the completion via its various then... and when... methods.
I'm trying to implement a Spring boot scheduler to test Callable and ExecutorService interfaces.
In my app I have:
#Bean("fixedThreadPool")
public ExecutorService fixedThreadPool() {
return Executors.newFixedThreadPool(5);
}
Then:
**#Scheduled(fixedRate = 60000)**
public void removeUserIds(Set<String> userIds) {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://localhost:8080/remove");
final List<Callable<String>> callables = new ArrayList<>();
userIds.forEach(userId -> {
final List<Callable<String>> callables = new ArrayList<>();
userIds.forEach(userId -> {
final Callable<String> task = () -> {
try{
log.info("Calling service to remove user id node : "+userId);
callServiceToRemoveNode(url,userId);
} catch(ServiceException e ){
log.error("Error while calling service: "+e.getCause());
**executor.shutdownNow();**
}
return "";
}; //Call to remote service using RestTemplate
callables.add(task);
});
try {
final List<Future<String>> futureList =
executor.invokeAll(callables);
futureList.forEach(future -> {
try {
log.info(future.get());
} catch (final Exception e) {
log.error("Error : "+ e.getMessage());
}
});
} catch (final Exception e) {
log.error("Error Error Error : "+ e.getMessage());
} finally {
executor.shutdown();
}
}
When I am calling removeUserIds() method with 100 userIds, It is working fine in happy flow, but if service is unavailable or down, error is getting printed 100th time and to avoid this I have used executor.shutdownNow(); so that further call will not happen to service for other user ids. But scheduler is not working and not executing after time interval if executor.shutdownNow(); statement executes. Could you please help me here to find out solution to avoid scheduler shutdown so even after executor.shutdownNow(); statement executes in before run of scheduler, it should run? or suggest feasible solution here?
I need to execute a ping webservice to check if I have connection to the endpoint and the webservice server is all fine.
It's kinda dumb but I have to call a webservice for this. The problem is that when I call the stub.ping(request) and I dont have connection it keeps trying to execute this code for like a minute... and then returns false.
Any way to make this timeout after 1 second if it cannot ping?
public boolean ping() {
try {
PingServiceStub stub = new PingServiceStub(soapGWEndpoint);
ReqPing request = new ReqPing();
UserInfo userInfo = new UserInfo();
userInfo.setName(soapGWUser);
userInfo.setPassword(soapGWPassword);
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.setConfigurationName(soapGWAppName);
stub.ping(request);
return true;
} catch (RemoteException | PingFault e) {
return false;
}
}
You could use something like the TimeLimiter from the Google Guava library. This allows you to wrap a callable in an operation that you can call with Timeout. If the callable does not complete the operation in time, it will throw a TimeoutException which you can catch and return false after one second.
As an example:
TimeLimiter timeLimiter = new SimpleTimeLimiter();
try {
String result = timeLimiter.callWithTimeout(
() -> callToPing(), 1, TimeUnit.SECONDS);
return true // Or something based on result
} catch (TimeoutException e) {
return false
}
You could execute your task asynchronously as runnable in a threadpool using ExecutorService :
ExecutorService executorService = Executors.newCachedThreadPool();
Runnable runnable = () -> {
stub.ping(request);
};
Future<?> submit = executorService.submit(runnable);
try {
submit.get(1, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
System.out.println("Task was being executed for more than 1 second");
//submit.cancel(true); to cancel this task and if it is responsive to interruption the task will finish
}
A TimeoutException will be thrown when task is being executed for more than the time you specified in get method. Note that the Future::get is a blocking operation.
In the following code intention is to achieve asynchronous execution of a task provided it runs in less than 100 ms else timeout exception from other thread would be thrown ,
Question : What happens to the thread that is executing asynchronously for more than 100 ms , would it be released ? or it would wait for the task to complete without throwing exception ? ( wrote the code thinking that acceptEither would terminate the long running task once it encounters the timeOutException from the other future)
private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public static <T> CompletableFuture<T> failAfter(long longValue) {
final CompletableFuture<T> timeoutFuture = new CompletableFuture<>();
scheduler.schedule(() -> {
final TimeoutException ex = new TimeoutException("Timing out");
return timeoutFuture.completeExceptionally(ex);
}, longValue, TimeUnit.MILLISECONDS);
return timeoutFuture;
}
final CompletableFuture<CustomResponse> CustomResponseFuture = CompletableFuture.supplyAsync(() -> object.taks()).
exceptionally(ex -> {
System.out.println("help");
return new "Hello";
});
CustomResponseFuture
.acceptEither(failAfter(100l), TesFutureStuff::myNewMethod)
.exceptionally(throwable -> {
System.out.println("failure "+throwable.getMessage());
return null;
})/*.getNow(null )*/;
If you just want a task that terminates after a specific amount of time, you don’t need CompletableFuture. Just create an ExecutorService, and call its invokeAny method.
If you insist on using CompletableFuture, you can use its get and cancel methods:
CompletableFuture<CustomResponse> future = CompletableFuture.supplyAsync(() -> object.task());
try {
CustomResponse response = future.get(100, TimeUnit.MILLISECONDS);
// process response here
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (TimeoutException e) {
System.out.println(e);
future.cancel(true);
}
Update:
To do the whole thing in the background, submit the invokeAny call to the same ExecutorService, but make sure the ExecutorService is not single threaded. There are many choices: Executors.newFixedThreadPool(2), Executors.newWorkStealingPool(), Executors.newCachedThreadPool, or even ForkJoinPool.commonPool().
For the CompletableFuture approach, I just noticed that as of Java 9, CompletableFuture adds an orTimeout method:
future.orTimeout(100, TimeUnit.MILLISECONDS);
I'm pretty new to Java multi threading, I've found a few responses for what I'm trying to do. However being new to java threading I'm still having a hard time following the responses.
Basically this is what I've got:
private final ExecutorService mFixedThreadPool;
public ThreadPool(int threadCount) {
mFixedThreadPool = Executors.newFixedThreadPool(threadCount);
}
public interface Task {
void phase1();
void phase2();
void phase3();
}
public void executeBatch(List<Runnable> tasks) {
tasks.forEach(task -> mFixedThreadPool.execute(task::phase1));
tasks.forEach(task -> mFixedThreadPool.execute(task::phase2));
tasks.forEach(task -> mFixedThreadPool.execute(task::phase3));
//only return on the main thread once all the tasks are complete.
//(Dont destroy threadpool as the "executeBatch" method will be called in a loop)
}
I want to pause or stop or wait on the thread that calls "executeBatch" until the batch of work is complete. I know it's possible to do this using mFixedThreadPool.shutdown() then waiting till its shutdown successfully, however I would like to reuse the threads many times very often so shutting down each time is inefficient.
If what you want is a thread pool that doesn't start the next thread until the previous one has finished you can simply create a FixedThreadPool with one thread:
ExecutorService threadPool = Executors.newFixedThreadPool(1);
If what you want is sleep your current thread until the pool has finished using shutdown. shutdown() is meant precisely for this kind of task, but after shutdown you will need to create a new ExecutorService:
threadPool.shutdown();
try {
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
...
}
You could encapsulate your ExecutorService in an ExecutorCompletionService. This will notify you when it finishes without shutting down the Executor, like you want. See some info here.
One last option is using Future. The get() method blocks until that thread has finished so you could:
ExecutorService threadPool = Executors.newFixedThreadPool(4);
List<Callable<String>> tasks = new ArrayList<>();
List<Future<String>> futures = new ArrayList<>();
List<String> result = new ArrayList<>();
tasks.stream().forEachOrdered(task -> futures.add(threadPool.submit(task)));
for (Future<String> future :futures) {
try {
result.add(future.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I think fork/join framework can give you what you want.
You can control the execution and if needed unfork tasks and compute it in main thread.