Event driven to continue request thread execution in Spring MVC - java

There is a method foo() in controller, which have to wait another method bar() triggered to continue execution.
#GetMapping("/foo")
public void foo(){
doSomething();
// wait until method bar() triggered
doAnotherSomething();
}
#GetMapping("/bar")
public void bar(){
// make foo() continue execute after being called
}
My solution is: saving a status flag in database/cache, while foo() is waiting, the thread loops searching if the status changed.
However, this solution will blocke request thread for seconds.
Is there any way to make foo() method run asynchronously, thus won't block thread execution?

This question is too broad. Yes you can use DeferredResult to finish a web request later. But doAnotherSomething() should actually do stuff asynchronously, otherwise you still end up using a thread, just not the one from the app server's pool. Which would be a waste since you can simply increase the app server's pool size and be done with it. "Offloading" work from it to another pool is a wild goose chase.
You achieve truly asynchronous execution when you wait on more than one action in a single thread. For example by using asynchronous file or socket channels you can read from multiple files/sockets at once. If you're using a database, the database driver must support asynchronous execution.
Here's an example of how to use the mongodb async driver:
#GetMapping("/foo")
public DeferredResult<ResponseEntity<?>> foo() {
DeferredResult<ResponseEntity<?>> res = new DeferredResult<>();
doSomething();
doAnotherSomething(res);
return res;
}
void doAnotherSomething(DeferredResult<ResponseEntity<?>> res) {
collection.find().first(new SingleResultCallback<Document>() {
public void onResult(final Document document, final Throwable t) {
// process (document)
res.setResult(ResponseEntity.ok("OK")); // finish the request
}
});
}

You can use CountDownLatch to wait till the dependent method is executed. For the sake of simplicity, I have used a static property. Make sure both methods have access to the same CountDownLatch object. ThreadLocal<CountDownLatch> could also be considered for this usecase.
private static CountDownLatch latch = new CountDownLatch(1);
#GetMapping("/foo")
public void foo(){
doSomething();
// wait until method bar() triggered
latch.await();
doAnotherSomething();
}
#GetMapping("/bar")
public void bar(){
// make foo() continue execute after being called
latch.countDown();
}

Related

Should I use Thread and .join or Callable along with Future and .get?

I am writing a simple thread that simply run a process and reads the InputStream.
While reading the input, if it finds a certain string it sets a boolean to true.
Then when I need to check that boolean I usually do this:
thread.start();
//some other code
thread.join();
thread.getBoolean();
Or should I instead use Callable along with Future? If so, the correct use would be like this?
Callable<Boolean> myTask = new Task();
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Boolean> future = executorService.submit(myTask);
//some other code
Boolean output = future.get();
System.out.println(output);
executorService.awaitTermination(3, TimeUnit.SECONDS);
executorService.shutdownNow();
In my opinion, it is much better to use interfaces for asynchronous events like this. It is clean, faster and reliable.
Instead of a bare thread class, we would implement a string processor class that has a listener interface, and a process method that would take the stream and as well as the string to look for within the stream. So the approximate implementatin would be as following:
StringProcessor.java
class StringProcessor {
public interface StringProcessorListener {
void onStringProcessingFinish(boolean found);
}
private ExecutorService executorService = Executors.newSingleThreadExecutor();
private StringProcessorListener listener;
public StringProcessor(StringProcessorListener listener) {
this.listener = listener;
}
public void process(InputStream inputStream, String strToFind) {
executorService.execute(()-> {
// Do the processing here...
while(inputStream.availlable() > 0) {
// Processing... maybe some string building or something else...
// Processing code goes here...
// A string built check it out
if(str.equals(strToFind)) {
// The string what we look for is found, notify the listener with true
listener.onStringProcessingFinish(true);
return;
}
// If reached here then the string not found, notify with false
listener.onStringProcessingFinish(false);
}
});
}
}
We would make use of this class from a superior class like following:
YourMainOrSuperiorClass.java
class YourMainOrSuperiorClass {
public static void main(String[] args) {
// Insantiate or get an input stream from where you wish...
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
// Search a string using the processor class
new StringProcessor(new StringProcessorListener {
#Override
public void onStringProcessingFinish(boolean found) {
if(found) {
// The string has been found, handle it
}
else {
// The String has not been found, handle it
}
}
})
.process(bufferedInputStream, "String to find");
// Maybe some more stuff to process from here...
}
}
As you can see, no need to block any thread using async interface patterns. When you invoke the StringProcessor.process() method, it will process the string within its internal thread without blocking the main thread, and you don't have to wait it to finish, on the contrary you can process more code meanwhile.
In the meantime, the StringProcessor will call the listener's onStringProcessingFinish() method as soon as the result is available and it will handled asynchronously from main thread while the main thread is taking care of something else.
Note that main thread should not return until the result is delivered in case of you need to update some UI elements or something else in the main thread. If this is the case you can manage it using a boolean flag, when main thread has been executed all of its stuff then enters to a busy waiting using that flag until the result is delivered. Once the result has delivered you can set that boolean flag accordingly then. It is like some kind of using the thread blocking method stuff.

How to call asynchronous method inside java thread?

In Java, is there any way to call and handle asynchronous method inside a thread?
Consider an scenario in which one of the method inside thread body takes more time to execute it. Because of that, thread completion takes more time.
I have tried some examples by using concurrency package classes like FutureTask and Executors.
Is it possible to implement and handle all exceptions inside asynchronous method? and Is it possible to get success or error responses like AJAX success and error handlers in JavaScript?
How will we ensure that asynchronous method successfully executed or not (with or without parent thread context)?
Most natural way of communication between async method and parent thread is standard class CompletableFuture:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class AsyncExample {
String input; // common data
// async method
public String toLower() {
return input.toLowerCase();
}
// method on main thread
public void run() {
input = "INPUT"; // set common data
try {
// start async method
CompletableFuture<String> future = CompletableFuture.supplyAsync(this::toLower);
// here we can work in parallel
String result = future.get(); // get the async result
System.out.println("input="+input+"; result="+result);
} catch (InterruptedException | ExecutionException e) {
}
}
public static void main(String[] args) {
new AsyncExample().run();
}
}
Note that creation and warming of an Executor, including the default executor used in the example, requires some time (50 ms on my computer), so you may want to create and warm one beforehand, e.g. by supplying an empty method:
CompletableFuture.supplyAsync(()->null).get();

Detecting a timed out Callable instance

I am performing some operations that are time sensitive and have a timeout associated with them.
This timeout mechanism is implemented using the Java Callable class.
The problem is that within the callable instance I execute an asynchronous task, with an anonymous interface implementation (listener).
My problem is that when the timeout triggers and the callable is cancelled. The async callback still executes and corrupts the state of my program.
How do I prevent these callbacks from firing? Do I just include a boolean specififying whether or not the timeout has ocurred or is there another way of achieving this please?
Thanks.
Code reference:
Callable<Object> callableTransaction = new Callable<Object>() {
#Override
public Object call() throws Exception {
Callback callback = new Callback() {
// Do stuff here and change program state.
};
performAsyncOperation(callback);
return ActionProcessor.OPERATION_COMPLETE;
}
};
Why don't you remove performAsyncOperation and perform the operation synchronously inside the call method.
And then, if you need any async operation, you can invoke your callableTransaction using performAsyncOperation or executor services.
Wrap your Callable in a java.util.concurrent.FutureTask... call task.cancel(true) when you want to cancel things. If your Callable is in a blocking operation (I/O, for example), then an exception will be thrown marking the interruption. Otherwise, your thread will need to check using Thread.isInterrupted() periodically to see if it should continue or abort.
Yes, this is mostly the same as including your own boolean flag, but you do get the benefit of blocking operations getting interrupted as well.
You have the right idea: Use a boolean flag to track whether the Callable has been interrupted. (I'm assuming that when you cancel the Callable, you are specifying that it should be interrupted.)
Use a concurrent class like CountDownLatch to make your Callable behave synchronously:
public Object call() throws Exception {
final AtomicBoolean aborted = new AtomicBoolean();
final CountDownLatch latch = new CountDownLatch(1);
Callback callback = new Callback() {
if (aborted.get()) {
return;
}
// Do stuff here and change program state.
latch.countDown(); // Tell Callable we're done.
};
performAsyncOperation(callback);
try {
latch.await(); // Wait for callback to finish.
} catch (InterruptedException e) {
aborted.set(true);
}
return ActionProcessor.OPERATION_COMPLETE;
}

How to cancel an ExecutorService in java

I wrote an application that runs some threads using ExecutorService and waits until they finish like this:
ExecutorService exService;
exService = Executors.newCachedThreadPool();
exService.execute(T1);
exService.execute(T2);
exService.shutdown();
boolean finshed = exService.awaitTermination(5, TimeUnit.MINUTES);
sometimes I need to cancel the execution of these threads (The entire ExecutorService).
I tried exService.shutdownNow() but it throws java.lang.InterruptedException and doesn't cancel threads.
How can I cancel execution of these threads?
EDIT: T1 class code added as nanda's request
public class TC implements Runnable{
private ExtractedDataBuffer Buffer;
private Scraper scraper;
private String AppPath;
private boolean Succeed=false;
private Map<String,Object> Result=null;
private JLabel StatElement;
public TC(ExtractedDataBuffer Buffer,String AppPath,String XMLfile,JLabel Stat) throws FileNotFoundException {
this.Buffer = Buffer;
this.AppPath=AppPath;
this.StatElement=Stat;
ScraperConfiguration config;
config = new ScraperConfiguration(AppPath + Main.XMLFilesPath +XMLfile);
scraper = new Scraper(config, AppPath);
}
private void extract(){
try{
mainF.SetIconStat("working", this.StatElement);
scraper.execute();
if(scraper.getStatus()==Scraper.STATUS_FINISHED){
this.Succeed=true;
Map<String,Object> tmp=new HashMap<String,Object>();
tmp.put("UpdateTime", ((Variable) scraper.getContext().get("UpdateTime")).toString().trim());
Buffer.setVal(this.Result);
mainF.SetIconStat("done", this.StatElement);
}else{
this.Succeed=false;
this.Result=null;
Buffer.setVal(null);
mainF.SetIconStat("error", this.StatElement);
}
}catch(Exception ex){
this.Succeed=false;
this.Result=null;
Buffer.setVal(null);
mainF.SetIconStat("error", this.StatElement);
}
}
public void run() {
this.extract();
}
}
If you change shutdown() to shutdownNow(), you are doing the correct thing in the code that you wrote. But then, check the documentation of shutdownNow():
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks. For example, typical implementations will
cancel via Thread.interrupt(), so any task that fails to respond to
interrupts may never terminate.
So probably your T1 and T2 are not coded in a correct way and don't respond to the interrupt well enough. Can you maybe copy the code for them?
--
Based on your code, I guess the code that takes long time is scraper.execute(), right? So inside those method, you have to constantly check something like this:
if (Thread.interrupted()) {
throw new InterruptedException();
}
If the interrupt come, the InterruptedException will be thrown and catched in your catch statement and the thread will stop.
My problem with Future#cancel() is that subsequent calls to get() throw a CancellationException. Sometimes I still want be able to call get() on the Future in order to retrieve a partial result after the shutdown of the executor service. In that case one can implement the termination logic in the callables that you submit to the executor service. Use a field like
private volatile boolean terminate;
public void terminate() {
terminate = true;
}
and check for terminate in the callable as often as required. In addition, you have to remember your callables somewhere so you can call terminate() on all of them.
Use the Executor.submit method, it extends base method Executor.execute(java.lang.Runnable) by creating and returning a Future that can be used to cancel execution and/or wait for completion:
task = Executor.submit( T1 )
...
task.cancel( true )

Java: Creating a multi threaded reader

I'm creating a reader application. The reader identifies based on the parameters which file to read, does some processing and returns the result to the caller.
I am trying to make this multi-threaded, so that multiple requests can be processed. I thought it was simple but later realized it has some complexity. Even though i create threads using executor service, I still need to return the results back to the caller. So this means waiting for the thread to execute.
Only way i can think of is write to some common location or db and let the caller pick the result from there. Is there any approach possible?
Maybe an ExecutorCompletionService can help you. The submitted tasks are placed on a queue when completed. You can use the methods take or poll depending on if you want to wait or not for a task to be available on the completion queue.
ExecutorCompletionService javadoc
Use an ExecutorService with a thread pool of size > 1, post custom FutureTask derivatives which override the done() method to signal completion of the task to the UI:
public class MyTask extends FutureTask<MyModel> {
private final MyUI ui;
public MyTask(MyUI toUpdateWhenDone, Callable<MyModel> taskToRun) {
super(taskToRun);
ui=toUpdateWhenDone;
}
#Override
protected void done() {
try {
// retrieve computed result
final MyModel computed=get();
// trigger an UI update with the new model
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ui.setModel(computed); // set the new UI model
}
});
}
catch(InterruptedException canceled) {
// task was canceled ... handle this case here
}
catch(TimeoutException timeout) {
// task timed out (if there are any such constraints).
// will not happen if there are no constraints on when the task must complete
}
catch(ExecutionException error) {
// handle exceptions thrown during computation of the MyModel object...
// happens if the callable passed during construction of the task throws an
// exception when it's call() method is invoked.
}
}
}
EDIT: For more complex tasks which need to signal status updates, it may be a good idea to create custom SwingWorker derivatives in this manner and post those on the ExecutorService. (You should for the time being not attempt to run multiple SwingWorkers concurrently as the current SwingWorker implementation effectively does not permit it.)

Categories

Resources