For some of HTTP requests from clients, there're very complex business logic in server side.
Some of these business logics doesn't require to response to the client immediately, like sending a email to somebody. Can I put those tasks in an asynchronous method,so I only need to ensure that they had been executed,I don't need to wait all tasks complete to respond to the user.
Updated: Some people asked about the framework I am using. I am using Struts2 + Spring.
You can use the following 'fire and forget' pattern:
new Thread(new Runnable(){
public void run(){
System.out.println("I Am Sending Email");
sendEmailFunction();
}
}).start();
But too many such threads will lead to trouble. If you are going to do this, then you should use a ThreadPoolExecutor to ensure that you have some control over thread production. At the very least, place a maximum on the number of threads.
I don't know what framework you're using, but, in basic Java, you can just create a new Thread:
interface MyTaskCallback {
void myTaskCallback();
}
class MyTask implements Runnable {
MyTaskCallback callback;
Thread me;
public MyTask(MyTaskCallback callback) {
this.callback = callback;
this.me = new Thread();
}
public void start() {
this.me = new Thread(this);
this.me.start();
}
public void stop() {
try {
this.me.join(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
// Calls here will not block the other threads
sendEmailRequest();
callback.myTaskCallback();
}
}
class Main implements MyTaskCallback {
public void foo() {
MyTask m = new MyTask(this);
m.start();
}
public void myTaskCallback() {
// called when MyTask completes
}
}
Yes. Read about concurrency.
You can probably set up an asynchronous producer/consumer queue, for example.
there is no "asynchroneous method" in java, but you will either use Threads (possibly through a framework like Quartz: http://www.quartz-scheduler.org/ ) or a message queue like JMS http://java.sun.com/products/jms/
You want to look at the java.util.concurrent.Executors. One way to solve your problem is to have a ScheduledExecutorService which keeps a Queue, and runs every so often. There are many different ways to offload work available in the concurrent utilities however, it depends on your requirements, how expensive the tasks are, how fast they need to be done, etc.
You should respond to all HTTP requests immediately, otherwise the client may think the server is not responding or timeout. However, you could start up other threads or processes to complete tasks in the background before you respond to the client.
You could also continue to send 100 responses until the task was complete.
Yes you can Servlet 3.0 has great asynchronous support.
Watch this its a really great resource, you can watch the entire cast if you are unfamiliar with Servlet 3.0.
A good run down of it here.
The api docs.
Spring has good support for Quartz scheduling as well as Java Threading. This link will give you better idea about it.
Can I put those tasks in an asynchronous method,so I don't need to wait all tasks complete to respond to the user ?
YES
Related
I'm exposing a legacy web app on GraphQL, but this web app uses Threadlocals (amongst other Apache-Shiro).
Since GraphQL-java seems to be using the fork-join pool for concurrency I worry about how far I need to go to ensure that my ThreadLocals still work and work safely.
Reading the documentation and the source it seems a large part of the concurrency is achieved by DataFetchers that return CompletableFuture's I can't tell for sure if that's the only source of concurrency (i think not) and whether the DataFetchers themselves are invoked from the fork-join pool
So would it be Safe to wrap my DataFetcher's in a delegate that set and clears the ThreadLocals? or does that still have the risk of being preempted and continued on another thread in the fork-join pool something like:
static class WrappedDataFetcher implements DataFetcher<Object> {
private DataFetcher<?> realDataFetcher;
WrappedDataFetcher(DataFetcher<?> realDataFetcher) {
this.realDataFetcher = realDataFetcher;
}
#Override
public Object get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception {
try {
setThreadLocalsFromRequestOrContext(dataFetchingEnvironment);
return realDataFetcher.get(dataFetchingEnvironment);
} finally {
clearTreadLocals();
}
}
}
Or would I need to explicitly run my DataFetchers in a Threadpool like:
static class WrappedDataFetcherThreadPool implements DataFetcher<Object> {
private DataFetcher<?> wrappedDataFetcher;
private ThreadPoolExecutor executor;
WrappedDataFetcherThreadPool(DataFetcher<?> realDataFetcher, ThreadPoolExecutor executor) {
// Wrap in Wrapper from previous example to ensure threadlocals in the executor
this.wrappedDataFetcher = new WrappedDataFetcher(realDataFetcher);
this.executor = executor;
}
#Override
public Object get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception {
Future<?> future = executor.submit(() -> wrappedDataFetcher.get(dataFetchingEnvironment));
return future.get(); //for simplicity / clarity of the question
}
}
I think the second one solves my problem but it feels like overkill and I worry about performance. But I think the first risks preemption.
If there is a better way to handle this I would love to hear it as well.
Note: this is not about the async nature of GraphQL (I hope to leverage that as well) but about the possible side effect of running multiple requests WITH treadLocals that might get mixed up between requests due to the fork-join pool
As far as I know graphql-java does not use its own thread pool and relies on the application for it. The way it achieves it using future callbacks. Say this is the current state of the application.
Thread T_1 with thread local storage TLS_1 executing data fetcher DF_1.
Graphql-java engine attaches a synchronous callback to the future returned by DF_1. If a future is not returned it wraps the result in a completed future and then attaches the synchronous callback. Since the callback is synchronous the thread that completes the future runs the callback. If any other thread apart from T_1 completes the future, TLS_1 is lost(unless it's copied over to the executing thread). One example of this is a non blocking HTTP I/O library which uses an I/O thread to complete the response future.
Here is a link where the authors have commented more on the thread behavior in graphql-java library
https://spectrum.chat/graphql-java/general/how-to-supply-custom-executor-service-for-data-fetchers-to-run-on~29caa730-9114-4883-ab4a-e9700f225f93
At the moment I have something like;
public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
new SomeAsyncTask(afterSomeAsyncTask).execute();
} else {
new DifferentAsyncTask(afterAnotherAsyncTask).execute();
}
}
PostExecute afterSomeAsyncTask = new PostExecute() {
void Callback(String response) {
doSomethingElse(response);
new DifferentAsyncTask(afterAnotherAsyncTask).execute();
}
}
}
This doesn't look too bad on the face of it, but I have hugely simplified the code and you can imagine how complex it becomes when you have more than a few calls going on and some branching starts to happen.
To help with context, the actual use case is normally something like;
use an sdk to get some device/user information
use the returned information to authenticate with a web service
send some logging info to the web service
get some data from the web service
get some other data from the web service
use that data to generate the UI
I would prefer my code to look a bit more like;
public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
new SomeAsyncTask().execute();
doSomethingElse(response);
}
new DifferentAsyncTask().execute();
afterAnotherAsyncTask();
}
}
I have tried used .get() in the past and had issues but never got to the bottom of why (potentially I was trying to call one AsyncTask inside another, which I've read is a no go- but it was a long time ago so can't be sure). Whilst I realise .get somewhat defeats the object of AsyncTask, I am only using it because Java forces me to (for network communication etc). My application is relying on the result to continue and can't do anything else till it returns anyway.
Should I try the .get() technique again? Or is it a really bad idea?
Should I just suck it up and realise the code is harder to read and I will need to jump to the callback methods to try and understand the code flow?
Or is there a different option?
I have also just learnt of Needle which looks like quite a nice library https://zsoltsafrany.github.io/needle/ and I think I could do more like;
NetworkService networkService = new NetworkService();
Needle.onBackgroundThread().serially().execute(networkService);
String result = doSomethingWithResponse(networkService.response);
AnotherNetworkService anotherNetworkService = new AnotherNetworkService(result);
Needle.onBackgroundThread().serially().execute(anotherNetworkService);
But perhaps this is exactly the same as the AsyncTask.get() approach?
The TL;DR of any answer really will be: Kotlin coroutines.
Take a look at ScheduledThreadPoolExecutor which you can obtain like:
ExecutorService executor = Executors.newScheduledThreadPool(8);
There are numerous methods for scheduling futures.
Your first example might look like:
public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
executor.submit(() -> /* async task */);
doSomethingElse(response);
}
executor.submit(() -> /* different async task */)
afterAnotherAsyncTask();
}
}
(Although you'll need to look at the specific methods for alternatives to block/join.)
I'm looking at the Simple RPC example from grpc.io's basic tutorial:
#Override
public void getFeature(Point request, StreamObserver<Feature> responseObserver) {
responseObserver.onNext(checkFeature(request));
responseObserver.onCompleted();
}
...
private Feature checkFeature(Point location) {
for (Feature feature : features) {
if (feature.getLocation().getLatitude() == location.getLatitude()
&& feature.getLocation().getLongitude() == location.getLongitude()) {
return feature;
}
}
// No feature was found, return an unnamed feature.
return Feature.newBuilder().setName("").setLocation(location).build();
}
Are there any caveats to interacting with the StreamObserver from other threads? For example, say checkFeature() asynchronously hits another service, returning a CompletableFuture:
#Override
public void getFeature(Point request, StreamObserver<Feature> responseObserver) {
checkFeature(request).
thenAccept(feature -> responseObserver.onNext(feature));
responseObserver.onCompleted();
}
Of course the above wouldn't work because the first thread would execute onCompleted() before the feature is returned. So let's fix that:
#Override
public void getFeature(Point request, StreamObserver<Feature> responseObserver) {
checkFeature(request).
thenAccept(feature -> {
responseObserver.onNext(feature);
responseObserver.onCompleted();
});
}
I think this should work, but I'm new to Java so I wonder what ramifications there are. For example,
Will Context.current() be consistent?
Will anything cause the StreamObserver to destruct or close prematurely besides onNext() for a unary calls and onError()?
Is there a better practice?
It would be great if someone could also step me through how they reasoned. I tried looking up actual implementations of StreamObserver but I wasn't sure what to look for.
Using thenAccept() to call onNext() and onCompleted() is fine, because the observer is not called concurrently from multiple threads.
The "broken" example that called onCompleted() separately was broken also because it could have called the observer from multiple threads without any form of synchronization. StreamObservers may not be called from multiple threads simultaneously.
Using thenAccept() isn't quite right though, as it doesn't handle the case where the future fails. So you need to receive the Throwable as well, which can be done with whenComplete():
#Override
public void getFeature(Point request, StreamObserver<Feature> responseObserver) {
checkFeature(request).
whenComplete((feature, t) -> {
if (t != null) {
responseObserver.onError(t);
} else {
responseObserver.onNext(feature);
responseObserver.onCompleted();
}
});
}
The Context could easily be "wrong" when processing that lambda. Typically we'd look for "architectural" solutions to make sure the context is propagated, like wrapping all application thread pools in Context.currentContextExecutor() when creating them, so individual call sites don't need to be concerned with propagation. I'm not familiar enough with CompletableFuture to provide strategy for it.
Will Context.current() be consistent?
Context.current() is using ThreadLocal. if you are accessing it on a different thread, it won't be consistent. You can propagate context between threads. You may find this post useful.
Will anything cause the StreamObserver to destruct or close prematurely besides onNext() for a unary calls and onError()?
Yes, Normal flow of StreamObserver ends with onError or onCompleted.
As StreamObserver javadoc states, "Since individual StreamObservers are not thread-safe, if multiple threads will be writing to a StreamObserver concurrently, the application must synchronize calls". If you are calling StreamObserver concurrently, you need to synchronize the calls. In other words, if you know for sure it won't be called concurrently even if you are using multiple threads, it should be fine.
If accessing the same StreamObserver on multiple threads, I would try to synchronize it unless the performance is critical since it is error prone. At least, it deserves a nice comment.
I've found a lot of examples about it and doesn't know what's the 'right' implementation right there.
Basically I've got a object (let's call it NBAManager) and there's a method public Completable generateGame() for this object. The idea is that generateGame method gets called a lot of times and I want to generate games in a sequential way: I was thinking about concurrent queue. I came up with the following design: I'd create a singleton instance of NBAService: service for NBAManager and the body of generateGame() will look like this:
public Completable generateGame(RequestInfo info)
return service.generateGame(info);
So basically I'll pass up that Completable result. And inside of that NBAService object I'll have a queue (a concurrent one, because I want to have an opportunity to poll() and add(request) if there's a call of generateGame() while NBAManager was processing one of the earlier requests) of requests. I got stuck with this:
What's the right way to write such a job queue in Rx way? There're so many examples of it. Could you send me a link of a good implementation?
How do I handle the logic of queue execution? I believe we've to execute if there's one job only and if there're many then we just have to add it and that's it. How can I control it without runnable? I was thinking about using subjects.
Thanks!
There are multiple ways to implement this, you can choose how much RxJava should be invoked. The least involvement can use a single threaded ExecutorService as the "queue" and CompletableSubject for the delayed completion:
class NBAService {
static ExecutorService exec = Executors.newSingleThreadedExecutor();
public static Completable generateGame(RequestInfo info) {
CompletableSubject result = CompletableSubject.create();
exec.submit(() -> {
// do something with the RequestInfo instance
f(info).subscribe(result);
});
return result;
}
}
A more involved solution would be if you wanted to trigger the execution when the Completable is subscribed to. In this case, you can go with create() and subscribeOn():
class NBAService {
public static Completable generateGame(RequestInfo info) {
return Completable.create(emitter -> {
// do something with the RequestInfo instance
emitter.setDisposable(
f(info).subscribe(emitter::onComplete, emitter::onError)
);
})
.subscribeOn(Schedulers.single());
}
}
currently, I have a web application based on Java 7, tomcat 7 and Spring 4 that invokes a thread on tomcat startup.
This thread is always alive and the java code is:
public class Scheduler {
Queue<Long> queue = new ArrayBlockingQueue<Long>();
private static class ThreadExecutor implements Runnable
{
.......
#Override
public void run()
{
while(true)
{
Long ID = queue.get();
if(ID != null)
{
Object o = webFacade.get(ID);
//Exec....
}
else
{
try
{
Thread.sleep(30000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
}
An external event fills the queue with the Object's ID.
With one tomcat this thread works well, but now I nedd to add onother tomcat, so I want to introduce Quartz in clustered mode.
I've configured Quartz in my project and it seems to work, but now how can I "translate" this class using Quartz?I want that only one thread is active because it is very expensive for my Database.
Thanks in advance
In general Quartz while being run in a cluster mode guarantees that the job will be triggered (and handled) on one server only.
So Job will be the task that you execute (in other words, what should be executed).
Now Quartz also introduces the concept of Trigger which basically defines when the job will be triggered.
From your code snippet, you run the job every 30000 ms = 30 seconds. So you'll trigger your stuff every 30 seconds (SimpleTrigger will do the job).
So, the 'while' loop goes away, it will be handled by quartz automatically.
In job you'll only work with a queue. Its unclear who fills this queue, but it looks like a different question.
It's hard to say exactly how you translate the queue, but in general job should
Get from queue
Call webFacade just like now
That's it. Last but not the least, Spring has a beautiful integration with Quartz. See Chapter 33.6.