@Async annotation
Given that the ratio of their areas is π / 4 , the value of π can be approximated using a Monte Carlo method.
Runnable is a functional
interface and has a single
run() method which doesn't accept
any parameters and does not return any values:
public interface Runnable {
public void run();
}
Callable is a generic interface
containing a single call() method –
which returns a value V:
public interface Callable<V> {
V call() throws Exception;
}
A Future represents the result of an asynchronous computation:
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException,
TimeoutException;
}
interface PiService {
Pi compute(int timeToComputeInSeconds)
}
class App {
ExecutorService exec = ...
PiService ps = ...
void show(int timeInSeconds) throws Exception {
Future<Pi> pi = exec.submit(() -> ps.compute(timeInSeconds));
displayOtherThings(); // do other things while computing π
displayPi(pi.get());
}
}
The FutureTask class is an
implementation of Future and
Runnable, and so may be executed by
an Executor.
FutureTask<Pi> pi =
new FutureTask<String>(new Callable<Pi>() {
public Pi call() {
return ps.compute(timeInSeconds);
}});
e.execute(pi);
With lambda
FutureTask<Pi> pi =
new FutureTask<String>(() -> ps.compute(timeInSeconds));
e.execute(pi);
@Service
public class PiService {
@Async
public Future<Pi> compute(int timeInSeconds) {
Pi pi = ...
return new AsyncResult<Pi>(pi);
}
}
@Configuration
@EnableAsync
public class TaskExecutorConfig {
@Bean public Executor taskExecutor() {
ThreadPoolTaskExecutor exe = new ThreadPoolTaskExecutor();
exe.setCorePoolSize(0);
exe.setQueueCapacity(0);
exe.setKeepAliveSeconds(10);
exe.setThreadNamePrefix("async-");
exe.setAllowCoreThreadTimeOut(true);
exe.initialize();
return exe;
}
}
Repository on github https://github.com/devonfw-java-advanced/concurrent contains branches:
Future and FutureTask
ExecutorService
Executor
@Async
The basis of the exercise, branch step-0
Sample solution, branch: step-1
Future does not have any
methods to combine the computations or handle possible errors.
CompletableFuture implements
the Future and the
CompletionStage. The last interface
defines the contract for an asynchronous computation step that we
can combine with other steps.
CompletableFuture has about 50
different methods for composing, combining, and executing
asynchronous computation steps and handling errors.
interface PiService {
Pi compute(int timeToComputeInSeconds)
}
class App {
PiService ps = ...
void show(int timeInSeconds) throws Exception {
CompletableFuture<Pi> pi = CompletableFuture
.supplyAsync(() -> ps.compute(timeInSeconds));
displayOtherThings(); // do other things while computing π
displayText(pi.get());
}
}
CompletableFuture<?> cs = CompletableFuture
.supplyAsync(
() -> piService.computePi(timeToComputePi1))
.thenApplyAsync(
pi -> pi.getComputedPi() * pi.getComputedPi())
.thenAcceptAsync(
result -> logger.info("result: {}", result));
displayOtherThings(); // do other things while computing and printing π*π
cs.join();
Repository on github https://github.com/devonfw-java-advanced/concurrent contains branches:
CompletableFuture
Use CompletableFuture to calculate the area of the circle with radius r
@Async@AsyncThe basis of the exercise, branch step-0
Sample solution, branch: step-2
@Configuration
public class MvcConfig {
@Bean public Executor mvcExecutor() {
return Executors.newCachedThreadPool();
}
@Bean public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override public void configureAsyncSupport(
final AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor(
new ConcurrentTaskExecutor(mvcExecutor()));
}};
}
}
@RestController
public class PiRest {
@Autowired
private PiMultiService ps;
@GetMapping("rest/pi")
public Callable<List<Pi>> pi(
@RequestParam(name = "timeInSeconds"), int timeInSeconds) {
return () -> {
return ps.computeMultiPis(timeInSeconds);
};
}
}
@RestController
public class PiRest {
@Autowired
private PiMultiService ps;
@GetMapping("rest/pi")
public DeferredResult<List<Pi>> pi(
@RequestParam(name = "timeInSeconds"), int timeInSeconds) {
DeferredResult<List<Pi>> result = new DeferredResult<>();
result.setResult(piService.computeMultiPis(
timeToComputeInSeconds, numberOfProbes));
return result;
}
}
Repository on github https://github.com/devonfw-java-advanced/asynchronous contains branches:
Asynchronicity in Servlet
The basis of the exercise, branch step-0
Sample solution, branch: step-1
Asynchronicity in Service
The basis of the exercise, branch step-1
Sample solution, branch: step-2