I am using a proprietary, 3rd party framework in my Android app -- EMDK from Zebra, to be specific -- and two of their exposed methods:
.read() and .cancelRead() are asynchronous, each taking anywhere from a split second to a 5 whole seconds to complete. I need to be able to spam them without crashing my application and ensure that each one isn't called twice in a row. How can I go about doing this? I don't have any access to the methods themselves and a decompiler will only give me runtime stubs.
Edit: I also have no idea when each of these two calls ever completes.
Changing asynchronous programs into blocking ones is a more general requirement to this problem.
In Java, we can do this with CountDownLatch (as well as Phaser), or LockSupport + Atomic.
For example, if it is required to change an asynchronous call asyncDoSomethingAwesome(param, callback) into a blocking one, we could write a "wrapper" method like this:
ResultType doSomethingAwesome(ParamType param) {
AtomicReference<ResultType> resultContainer = new AtomicReference<>();
Thread callingThread = Thread.currentThread();
asyncDoSomethingAwesome(param, result -> {
resultContainer.set(result);
LockSupport.unpark(callingThread);
});
ResultType result;
while ((result = resultContainer.get()) == null) {
LockSupport.park();
}
return result;
}
I think this will be enough to solve your problem. However, when we are writing blocking programs, we usually want a "timeout" to keep the system stable even when an underlying interface is not working properly, for example:
ResultType doSomethingAwesome(ParamType param, Duration timeout) throws TimeoutException {
AtomicReference<ResultType> resultContainer = new AtomicReference<>();
Thread callingThread = Thread.currentThread();
asyncDoSomethingAwesome(param, result -> {
resultContainer.set(result);
LockSupport.unpark(callingThread);
});
ResultType result;
long deadline = Instant.now().plus(timeout).toEpochMilli();
while ((result = resultContainer.get()) == null) {
if (System.currentTimeMillis() >= deadline) {
throw new TimeoutException();
}
LockSupport.parkUntil(deadline);
}
return result;
}
Sometimes we need more refined management to the signal among threads, especially when writing concurrency libries. For example, when we need to know whether the blocking thread received the signal from another thread calling LockSupport.unpark, or whether that thread successfully notified the blocking thread, it is usually not easy to implement with Java standard library. Thus I designed another library with more complete mechanism to solve this issue:
https://github.com/wmx16835/experimental_java_common/blob/master/alpha/src/main/java/mingxin/wang/common/concurrent/DisposableBlocker.java
With the support of DisposableBlocker, life will become much easier :)
ResultType doSomethingAwesome(ParamType param, Duration timeout) throws TimeoutException {
// We can use org.apache.commons.lang3.mutable.MutableObject instead of AtomicReference,
// because this object will never be accessed concurrently
MutableObject<ResultType> resultContainer = new MutableObject<>();
DisposableBlocker blocker = new DisposableBlocker();
asyncDoSomethingAwesome(param, result -> {
resultContainer.setValue(result);
blocker.unblock();
});
if (!blocker.blockFor(timeout)) {
throw new TimeoutException();
}
return resultContainer.getValue();
}
Might be off on this as I'm not 100% sure what you're trying to achieve/nor the structure, but could you wrap each in an AsyncTask? Then in a parent AsyncTask or background thread:
AsyncTask1.execute().get(); //get will block until complete
AsyncTask2.execute().get(); //get will block until complete
This is assuming there is some way of knowing the calls you're making completed.
Related
I have been working with some Reactor Core Java, because I want to figure out if this is possible to solve one problem I currently have using this framework.
At present I have a long, executing job that takes about 40-50 minutes to complete. The method looks more or less like this:
public void doLongTask(List<Something> list){
//instructions.
for(Something sm : list){
if(condition){
executeLongOperation();
}
//instructions
if(condition){
executeLongOperation();
}
}
}
in my controller I have something like this:
#GetMapping(path = "/integersReactor", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
#ResponseBody
public Flux<Integer> getIntegersReactor(){
logger.debug("Request getIntegersReactor initialized.");
return simpleSearchService.getIntegersReactor();
}
and in the service layer I have something like this:
#Override
public Flux<Integer> getIntegersReactor(){
return Flux.range(0, Integer.MAX_VALUE);
}
this is just a placeholder that I am using as a proof of concept. My real intentions are to somehow return a Flux of some object that I will define myself, this object will have a few fields that I will use to tell the consumer the status of the job.
Now, things get somewhat complicated now because I would like to send updates as the executeLongOperation(); are executed, and somehow instead of returning a flux of Integers, return a flux of an object that uses the return of executeLongOperation();
Can this be acomplished with Flux? How can I leverage Reactor Core java to push the return values of all of the times executeLongOperation(); is executed into a reactive stream that can be passed to the controller the same way that getIntegersReactor() does it in my example?
Yes it should be possible, but since the executeLongOperation is blocking, it will need to be offset on a dedicated thread (which reduces the benefits you get from a top-to-bottom reactive implementation).
Change your doLongTask to return a Flux<Foo>, make it concatenate Monos that wrap executeLongOperation on a dedicated thread (or better yet, change the executeLongOperation itself to return a Mono<Foo> and do the wrapping internally and subscribeOn another thread internally). Something like:
public Flux<Foo> doLongTask(List<Something> list) {
return Flux.fromIterable(list)
//ensure `Something` are published on a dedicated thread on which
//we can block
.publishOn(Schedulers.elastic()) //maybe a dedicated Scheduler?
//for each `Something`, perform the work
.flatMap(sm -> {
//in case condition is false, we'll avoid long running task
Flux<Foo> work = Flux.empty();
//start declaring the work depending on conditions
if(condition) {
Mono<Foo> op = Mono.fromCallable(this::executeLongOperation);
work = conditional.concatWith(op);
}
//all other instructions should preferably be non-blocking
//but since we're on a dedicated thread at this point, it should be ok
if(condition) {
Mono<Foo> op = Mono.fromCallable(this::executeLongOperation);
work = conditional.concatWith(op);
}
//let the flatMap trigger the work
return work;
});
}
This question already has answers here:
Java executors: how to be notified, without blocking, when a task completes?
(12 answers)
Closed 7 years ago.
I am working on a Java project that uses certain APIs that are blocking.
I would like to use asynchronous programming and callbacks, so that I don't have to block while waiting for the result. I've looked into using Java Future, but the only way I think I could use it is by calling the get() method which would block. I am open to using other ways to do asynchronous programming as well.
My current code looks like this.
Object res = blockingAPI();
sendToClient(res);
If I were to use Future, I would do it like this. But my understanding is get() is blocking.
private final int THREADS = Runtime.getRuntime().availableProcessors();
private ExecutorService executor = Executors.newFixedThreadPool(THREADS);
public void invokeApi() {
Future<Object> future = executor.submit(new Callable<Object>() {
public Object call() {
return result;
}
});
Object result = future.get(5, TimeUnit.SECONDS)
}
How could I go about implementing this such that the function of get() is basically handled by a callback that automatically gets invoked when the result is available?
Several options.
One is to wrap your future into a CompletableFuture:
public static <T> CompletableFuture<T> makeCompletableFuture(Future<T> future) {
return CompletableFuture.supplyAsync(() -> {
try {
return future.get();
} catch (InterruptedException|ExecutionException e) {
throw new RuntimeException(e);
}
});
}
An other one is to use Guava ListenableFuture:
ListeningExecutorService service = MoreExecutors.listeningDecorator(executor);
ListenableFuture<T> future = service.submit(callable);
Futures.addCallback(future, new FutureCallback<T>() {
public void onSuccess(T t) {
// ...
}
public void onFailure(Throwable thrown) {
// ...
}
});
You can also use Akka Futures which are highly composable.
You have two fundamental options :
periodically pool for result:
Future API offers method isDone() to check if computation result of Callable is ready. This is non-blocking method which returns boolean value, true if result is ready, otherwise false.
subscribe to result and do useful work while waiting for notification that result is ready. There are many ways to achieve this and probably the most simple one would be to use Observer Pattern.
Some other useful patterns which could be used in asynchronous programming, albeit not so well know, are Active object and Half sync - half async.
Active object works in a way that clients invoke services of concurrent objects with blocking. There is a schedule mechanism which processes these result by priority, as they come or whichever other criteria.
In example bellow, there is an implementation where client services are wrapped into Runnable, but you could easily change it to wrap services into Callable instead, and put proxy between Client and Active object to subscribe on result from callable.
Active object
I've written following multi thread program. I want to cancel the all the thread if one of the thread sends back false as return. However though I'm canceling the thread by canceling individual task. Its not working. What changes I need to make inorder to cancel the thread?
I've written following multi thread program. I want to cancel the all the thread if one of the thread sends back false as return. However though I'm canceling the thread by canceling individual task. Its not working. What changes I need to make inorder to cancel the thread?
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
public class BeamWorkerThread implements Callable<Boolean> {
private List<BeamData> beamData;
private String threadId;
public BeamScallopingWorkerThread(
List<BeamData> beamData, String threadId) {
super();
this.beamData = beamData;
this.threadId = threadId;
}
#Override
public Boolean call() throws Exception {
Boolean result = true;
DataValidator validator = new DataValidator();
Iterator<BeamScallopingData> it = beamData.iterator();
BeamData data = null;
while(it.hasNext()){
data = it.next();
if(!validator.validateDensity(data.getBin_ll_lat(), data.getBin_ll_lon(), data.getBin_ur_lat(), data.getBin_ur_lon())){
result = false;
break;
}
}
return result;
}
}
ExecutorService threadPool = Executors.newFixedThreadPool(100);
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
long count = 0;
final long RowLimt = 10000;
long threadCount = 1;
while ((beamData = csvReader.read(
BeamData.class, headers1, processors)) != null) {
if (count == 0) {
beamDataList = new ArrayList<BeamData>();
}
beamDataList.add(beamData);
count++;
if (count == RowLimt) {
results.add(threadPool
.submit(new BeamWorkerThread(
beamDataList, "thread:"
+ (threadCount++))));
count = 0;
}
}
results.add(threadPool.submit(new BeamWorkerThread(
beamDataList, "thread:" + (threadCount++))));
System.out.println("Number of threads" + threadCount);
for (Future<Boolean> fs : results)
try {
if(fs.get() == false){
System.out.println("Thread is false");
for(Future<Boolean> fs1 : results){
fs1.cancel(true);
}
}
} catch(CancellationException e){
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} finally {
threadPool.shutdownNow();
}
}
My comments
Thanks all for your input I'm overwhelmed by the response. I do know that, well implemented thread takes an app to highs and mean time it a bad implementation brings the app to knees. I agree I'm having fancy idea but I don't have other option. I've a 10 million plus record hence I will have memory constraint and time constraint. I need to tackle both. Hence rather than swallowing whole data I'm breaking it into chunks and also if one data is invalid i don't want to waste time in processing remaining million data. I find #Mark Peters suggestion is an option. Made the changes accordingly I mean added flag to interrupt the task and I'm pretty confused how the future list works. what I understand is that looping through each field of future list starts once all the thread returns its value. In that case, there is no way to cancel all the task in half way from main list. I need to pass on the reference of object to each thread. and if one thread finds invalid data using the thread refernce call the cancel mathod of each thread to set the interrupt flag.
while(it.hasNext() && !cancelled) {
if(!validate){
// loop through each thread reference and call Cancel method
}
}
Whatever attempt you make to cancel all the remaining tasks, it will fail if your code is not carefully written to be interruptible. What that exactly entails is beyond just one StackOverflow answer. Some guidelines:
do not swallow InterruptedException. Make its occurrence break the task;
if your code does not spend much time within interruptible methods, you must insert explicit Thread.interrupted() checks and react appropriately.
Writing interruptible code is in general not beginner's stuff, so take care.
Cancelling the Future will not interrupt running code. It primarily serves to prevent the task from being run in the first place.
While you can provide a true as a parameter, which will interrupt the thread running the task, that only has an effect if the thread is blocked in code that throws an InterruptedException. Other than that, nothing implicitly checks the interrupted status of the thread.
In your case, there is no blocking; it's busy work that is taking time. One option would be to have a volatile boolean that you check at each stage of your loop:
public class BeamWorkerThread implements Callable<Boolean> {
private volatile boolean cancelled = false;
#Override
public Boolean call() throws Exception {
//...
while(it.hasNext() && !cancelled) {
//...
}
}
public void cancel() {
cancelled = true;
}
}
Then you would keep references to your BeamWorkerThread objects and call cancel() on it to preempt its execution.
Why don't I like interrupts?
Marko mentioned that the cancelled flag above is essentially reinventing Thread.interrupted(). It's a valid criticism. Here's why I prefer not to use interrupts in this scenario.
1. It's dependent on certain threading configurations.
If your task represents a cancellable piece of code that can be submitted to an executor, or called directly, using Thread.interrupt() to cancel execution in the general case assumes that the code receiving the interrupt will be the code that should know how to cleanly cancel the task.
That might be true in this case, but we only know so because we know how both the cancel and the task work internally. But imagine we had something like this:
Task does piece of work
Listeners are notified on-thread for that first piece of work
First listener decides to cancel the task using Thread.interrupt()
Second listener does some interruptible piece of work, and is interrupted. It logs but otherwise ignores the interrupt.
Task does not receive interrupt, and task is not cancelled.
In other words, I feel that interrupt() is too global of a mechanism. Like any shared global state, it makes assumptions about all of the actors. That's what I mean by saying that using interrupt() exposes/couples to details about the run context. By encapsulating it in a cancel() method applicable only for that task instance, you eliminate that global state.
2. It's not always an option.
The classic example here is an InputStream. If you have a task that blocks on reading from an InputStream, interrupt() will do nothing to unblock it. The only way to unblock it is to manually close the stream, and that's something best done in a cancel() method for the task itself. Having one way to cancel a task (e.g. Cancellable), regardless of its implementation, seems ideal to me.
Use the ExecutorService.shutdownNow() method. It will stop the executor from accepting more submissions and returns with the Future objects of the ongoing tasks that you can call cancel(true) on to interrupt the execution. Of course, you will have to discard this executor as it cannot be restarted.
The cancel() method may not terminate the execution immediately if the Thread is not waiting on a monitor (not blocked interruptibly), and also if you swallow the InterruptedException that will be raised in this case.
e.g. I looking to find a way to execute #Async method not absolutely asynchronously.
For example I want to invoke #Asynctask that will block my process for a up to a maximum defined time if task still haven't completed.
#Async
public Future<ModelObject> doSomething() {
//here we will block for a max allowed time if task still haven't been completed
}
So such code will be semi asynchronous but the blocking time can be controlled by developer.
P.S : of course I can achieve this by simply blocking calling thread for a limited time. but I look to achieve that within spring layer
In short, no, there is no way to configure Spring to do this.
The #Async annotation is handled by the AsyncExecutionInterceptor which delegates the work to a AsyncTaskExecutor. You could, in theory, write your own implementation of the AsyncTaskExecutor but even then there would be no way to use the #Async annotation to pass the desired wait time to your executor. Even then, it's not clear to me what the caller's interface would look like since they'd still be getting a Future object back. You would probably also need to subclass the Future object as well. Basically, by the time you are finished, you will have written the entire feature again more or less from scratch.
You could always wrap the returned Future object in your own WaitingFuture proxy which provides an alternate get implementation although even then you'd have no way of specifying the wait value on the callee side:
WaitingFuture<ModelObject> future = new WaitingFuture<ModelObject>(service.doSomething());
ModelObject result = future.get(3000); //Instead of throwing a timeout, this impl could just return null if 3 seconds pass with no answer
if(result == null) {
//Path A
} else {
//Path B
}
Or if you don't want to write your own class then just catch the TimeoutException.
Future<ModelObject> future = doSomething();
try {
ModelObject result = future.get(3000,TimeUnit.MILLISECONDS);
//Path B
} catch (TimeoutException ex) {
//Path A
}
You can do it with an #Async method that returns a Future:
Future<String> futureString = asyncTimeout(10000);
futureString.get(5000, TimeUnit.MILLISECONDS);
#Async
public Future<String> asyncTimeout(long mills) throws InterruptedException {
return new AsyncResult<String>(
sleepAndWake(mills)
);
}
public String sleepAndWake(long mills) throws InterruptedException{
Thread.sleep(mills);
return "wake";
}
I'm trying to understand how to ensure that a specific action completes in a certain amount of time. Seems like a simple job for java's new util.concurrent library. However, this task claims a connection to the database and I want to be sure that it properly releases that connection upon timeout.
so to call the service:
int resultCount = -1;
ExecutorService executor = null;
try {
executor = Executors.newSingleThreadExecutor();
FutureTask<Integer> task = new CopyTask<Integer>();
executor.execute(task);
try {
resultCount = task.get(2, TimeUnit.MINUTES);
} catch (Exception e) {
LOGGER.fatal("Migrate Events job crashed.", e);
task.cancel(true);
return;
}
} finally {
if (executor != null) {
executor.shutdown();
}
The task itself simply wrapps a callable, here is the call method:
#Override
public Integer call() throws Exception {
Session session = null;
try {
session = getSession();
... execute sql against sesssion ...
}
} finally {
if (session != null) {
session.release();
}
}
}
So, my question for those who've made it this far, is: Is session.release() garaunteed to be called in the case that the task fails due to a TimeoutException? I postulate that it is no, but I would love to be proven wrong.
Thanks
edit: The problem I'm having is that occasionally the sql in question is not finishing due to wierd db problems. So, what I want to do is simply close the connection, let the db rollback the transaction, get some rest and reattempt this at a later time. So I'm treating the get(...) as if it were like killing the thead. Is that wrong?
When you call task.get() with a timeout, that timeout only applies to the attempt to obtain the results (in your current thread), not the calculation itself (in the worker thread). Hence your problem here; if a worker thread gets into some state from which it will never return, then the timeout simply ensures that your polling code will keep running but will do nothing to affect the worker.
Your call to task.cancel(true) in the catch block is what I was initially going to suggest, and this is good coding practice. Unfortunately this only sets a flag on the thread that may/should be checked by well-behaved long-running, cancellable tasks, but it doesn't take any direct action on the other thread. If the SQL executing methods don't declare that they throw InterruptedException, then they aren't going to check this flag and aren't going to be interruptable via the typical Java mechanism.
Really all of this comes down to the fact that the code in the worker thread must support some mechanism of stopping itself if it's run for too long. Supporting the standard interrupt mechanism is one way of doing this; checking some boolean flag intermittently, or other bespoke alternatives, would work too. However there is no guaranteed way to cause another thread to return (short of Thread.stop, which is deprecated for good reason). You need to coordinate with the running code to signal it to stop in a way that it will notice.
In this particular case, I expect there are probably some parameters you could set on the DB connection so that the SQL calls will time out after a given period, meaning that control returns to your Java code (probably with some exception) and so the finally block gets called. If not, i.e. there's no way to make the database call (such as PreparedStatement.execute()) return control after some predetermined time, then you'll need to spawn an extra thread within your Callable that can monitor a timeout and forcibly close the connection/session if it expires. This isn't very nice though and your code will be a lot cleaner if you can get the SQL calls to cooperate.
(So ironically despite you supplying a good amount of code to support this question, the really important part is the bit you redacted: "... execute sql against sesssion ..." :-))
You cannot interrupt a thread from the outside, so the timeout will have no effect on the code down in the JDBC layer (perhaps even over in JNI-land somewhere.) Presumably eventually the SQL work will end and the session.release() will happen, but that may be long after the end of your timeout.
The finally block will eventually execute.
When your Task takes longer then 2 minutes, a TimeoutException is thrown but the actual thread continues to perform it's work and eventually it will call the finally block. Even if you cancel the task and force an interrupt, the finally block will be called.
Here's a small example based in your code. You can test these situations:
public static void main(String[] args) {
int resultCount = -1;
ExecutorService executor = null;
try {
executor = Executors.newSingleThreadExecutor();
FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
try {
Thread.sleep(10000);
return 1;
} finally {
System.out.println("FINALLY CALLED!!!");
}
}
});
executor.execute(task);
try {
resultCount = task.get(1000, TimeUnit.MILLISECONDS);
} catch (Exception e) {
System.out.println("Migrate Events job crashed: " + e.getMessage());
task.cancel(true);
return;
}
} finally {
if (executor != null) {
executor.shutdown();
}
}
}
Your example says:
copyRecords.cancel(true);
I assume this was meant to say:
task.cancel(true);
Your finally block will be called assuming that the contents of the try block are interruptible. Some operations are (like wait()), some operations are not (like InputStream#read()). It all depends on the operation that that the code is blocking on when the task is interrupted.