I've been downloading and parsing a webpage with Jsoup, to show the content in a list. This process takes a while so I implemented Callable interface to do the task in another thread and get the result back.
The problem is that it still blocks UI during the process.
public class GetListaNotizie implements Callable<ArrayList<Notizia>> {
static ArrayList<Notizia> getNotizieBySezione() {
[...] Long process
return notizie;
}
#Override
public ArrayList<Notizia> call() throws Exception {
return getNotizieBySezione();
}
}
And then:
final ExecutorService service;
final Future<ArrayList<Notizia>> task;
service = Executors.newFixedThreadPool(1);
task = service.submit(new GetListaNotizie());
try {
ArrayList<Notizia> notizie = task.get();
lvListaNotizie.setAdapter(new RiempiLista(activity, notizie));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
What am I missing?
Because ... you're submitting your Callable to the pool, then explicitly blocking the thread waiting for it to finish.
ArrayList<Notizia> notizie = task.get();
I missed the Android tag on your Q. You're re-inventing the wheel here. Android provides AsyncTask for exactly this use case. See the AsyncTask example under Processes and Threads for an example of how it works.
(original answer follows)
You need your Callable to update/notify the UI when it's finished. One possible approach would be to pass a reference to the list you mention to your Callable.
Edit to add from comments:
Right now, you submit your Callable to the pool. Then you sit there waiting for it to finish (blocking the UI thread). Then you do this:
lvListaNotizie.setAdapter(new RiempiLista(activity, notizie));
Pass lvListaNotizie to your GetListaNotizie via a constructor and have that happen at the end of call() instead of returning the list to the Future. I don't know what lvListaNotizie is; if it's not thread-safe you will want to synchronize on it.
AsyncTask is deprecated since API level 30.
You can use coroutines documentation link for async code
or you can use work manager for async long-running operations documentation link
it is too late to answer but may be useful for new developers.
Related
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;
}
I have a situation where I'm using a Thread, she call a method that will do multiple processes, I need to use a "cancel" button in which you have to stop the thread, I not can use: "while" ,to verify that it was canceled because it not has loop in this process.
Ex:
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
controller = new FirstEtapaController();
execProcess();
return null;
}
};
new Thread(task).start();
Call Method
private void execProcess() {
Thread thread = new Thread(new Runnable() {
public void run() {
getController().execMhetod();
refreshTable();
}
});
thread.start();
thread.join();
};
Ie, I need to stop this process, even when the "ExecMethod" already running, it will take minutes, so I've gotta stop it and not have to wait for him to finish so that , others do not continues.
Remembering that this process will do iteration with my DAO.
The only way (well behaved way) is to add logic points in you spawned threads to check for an interrupted state. You can choose to use the built-in Thread.interrupt() mechanisms, or add your own logic using some form of thread-safe variable (an AtomicBoolean?) or a Semaphore of some sort.
If you use the Thread.interrupt() then your child processes will throw an InterruptedException when they encounter certain conditions, like Thread.wait() and other methods which require synchronization or use the java.util.concurrent.* classes.
You will need to (should already be) handle the InterruptedExceptions in the threads anyway, but perhaps you will need to put regular 'checks' in your child processes to look for the interrupted state anyway (can use Thread.isInterrupted() )
It is worth reading this Handling InterruptedException in Java
If instead of a raw Thread if you use an ExecutorService you'll end up with lots of additional methods/levers to control your threads, one of which is shutdownAll() which uses Thread.interrupt() to kill your thread and lets you check thread status via isTerminated()
Your user interface does not have to wait for the worker thread to finish, so don't worry too much about that.
Alas, Thread.destroy() and Thread.stop() are deprecated, due to bad implementations. I don't think there is a good "sig-kill" type of substitute for Java threads. You are going to have to recode the worker to check an abort flag of some kind, if it matters much. Otherwise, just let it waste a little CPU. ("you can't cancel that Save -- I've already done it!", in effect)
Whether or not a task can be canceled really depends on its implementation. Typically it intermittently checks a flag whether it should continue or not.
You can implement such a flag yourself, and a method to set it :
private volatile boolean shouldStop;
public void cancel() {
shouldStop = true;
}
#Override
public void run() {
while (!shouldStop) {
// do work
}
}
But threads already come with a flag : the interrupted flag. And while it is not necessarily used for canceling a thread, it is typical to use it for exactly that purpose. In fact the standard ExecutorService implementations will try to cancel their threads by interrupting them.
Aside from that several blocking methods (methods that put a thread in BLOCKED or WAITING state) will throw an InterruptedException when the thread is interrupted, at which point they become RUNNABLE again. This is something the previous approach with a boolean flag cannot achieve.
Therefore it is a better approach to use interruption to allow a task to be canceled. And you do not really need that cancel() method any more either :
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// do work
}
}
As a bonus, any code that knows your thread, knows how to cancel it. Including standard ExecutorService implementations.
Care should be taken when catching an InterruptedException, since doing that clears the interrupted flag. It is adviseable to always restore the interrupted flag when catching the Exception, so clients also know it's time to stop doing what they're doing.
private BlockingQueue<Integer> queue;
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Integer id = queue.take(); // blocking method
// do work
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
To cancel a thread, you can simply keep a reference to the Thread object and call interrupt() on it :
Thread thread = new Thread(new InterruptibleTask());
thread.start();
// some time after :
thread.interrupt();
But a more elegant approach is keeping tabs on your task (and not so much the specific thread it runs on) through a Future object. You can do this by wrapping your Runnable or Callable in a FutureTask.
RunnableFuture<Void> task = new FutureTask<>(new InterruptibleTask(), null);
new Thread(task).start();
// some time after :
task.cancel(true); // true indicating interruption may be used to cancel.
A Future is key in controlling your task. It allows you to wait for its completion, and optionally receive a value the task calculated :
try {
String value = future.get(); // return value is generically typed String is just as example.
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // since future.get() blocks
} catch (ExecutionException e) {
logger.log(Level.SEVERE, "Exception on worker thread", e.getCause()); // the ExecutionException's cause is the Exception that occurred in the Task
}
If you have several tasks (or even just one) it is worth using an ExecutorService :
ExecutorService pool = Executors.newCachedThreadPool();
Future<?> submit = pool.submit(new InterruptibleTask());
pool.shutdownNow(); // depending on ExecutorService implementation this will cancel all tasks for you, the ones Executors returns do.
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.)
How should I choose between ExecutorService's submit or execute, if the returned value is not my concern?
If I test both, I didn't see any differences among the two except the returned value.
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.execute(new Task());
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.submit(new Task());
There is a difference concerning exception/error handling.
A task queued with execute() that generates some Throwable will cause the UncaughtExceptionHandler for the Thread running the task to be invoked. The default UncaughtExceptionHandler, which typically prints the Throwable stack trace to System.err, will be invoked if no custom handler has been installed.
On the other hand, a Throwable generated by a task queued with submit() will bind the Throwable to the Future that was produced from the call to submit(). Calling get() on that Future will throw an ExecutionException with the original Throwable as its cause (accessible by calling getCause() on the ExecutionException).
execute: Use it for fire and forget calls
submit: Use it to inspect the result of method call and take appropriate action on Future objected returned by the call
From javadocs
submit(Callable<T> task)
Submits a value-returning task for execution and returns a Future
representing the pending results of the task.
Future<?> submit(Runnable task)
Submits a Runnable task for execution and returns a Future representing that
task.
void execute(Runnable command)
Executes the given command at some time in the future. The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.
You have to take precaution while using submit(). It hides exception in the framework itself unless you embed your task code in try{} catch{} block.
Example code: This code swallows Arithmetic exception : / by zero.
import java.util.concurrent.*;
import java.util.*;
public class ExecuteSubmitDemo{
public ExecuteSubmitDemo()
{
System.out.println("creating service");
ExecutorService service = Executors.newFixedThreadPool(10);
//ExtendedExecutor service = new ExtendedExecutor();
service.submit(new Runnable(){
public void run(){
int a=4, b = 0;
System.out.println("a and b="+a+":"+b);
System.out.println("a/b:"+(a/b));
System.out.println("Thread Name in Runnable after divide by zero:"+Thread.currentThread().getName());
}
});
service.shutdown();
}
public static void main(String args[]){
ExecuteSubmitDemo demo = new ExecuteSubmitDemo();
}
}
output:
java ExecuteSubmitDemo
creating service
a and b=4:0
Same code throws by replacing submit() with execute() :
Replace
service.submit(new Runnable(){
with
service.execute(new Runnable(){
output:
java ExecuteSubmitDemo
creating service
a and b=4:0
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
at ExecuteSubmitDemo$1.run(ExecuteSubmitDemo.java:14)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
How to handle the these type of scenarios while using submit()?
Embed your Task code ( Either Runnable or Callable implementation) with try{} catch{} block code
Implement CustomThreadPoolExecutor
New solution:
import java.util.concurrent.*;
import java.util.*;
public class ExecuteSubmitDemo{
public ExecuteSubmitDemo()
{
System.out.println("creating service");
//ExecutorService service = Executors.newFixedThreadPool(10);
ExtendedExecutor service = new ExtendedExecutor();
service.submit(new Runnable(){
public void run(){
int a=4, b = 0;
System.out.println("a and b="+a+":"+b);
System.out.println("a/b:"+(a/b));
System.out.println("Thread Name in Runnable after divide by zero:"+Thread.currentThread().getName());
}
});
service.shutdown();
}
public static void main(String args[]){
ExecuteSubmitDemo demo = new ExecuteSubmitDemo();
}
}
class ExtendedExecutor extends ThreadPoolExecutor {
public ExtendedExecutor() {
super(1,1,60,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(100));
}
// ...
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (t != null)
System.out.println(t);
}
}
output:
java ExecuteSubmitDemo
creating service
a and b=4:0
java.lang.ArithmeticException: / by zero
if you dont care about the return type, use execute. it's the same as submit, just without the return of Future.
Taken from the Javadoc:
Method submit extends base method {#link Executor#execute} by creating and
returning a {#link Future} that can be used to cancel execution and/or wait for
completion.
Personally I prefer the use of execute because it feels more declarative, although this really is a matter of personal preference.
To give more information: in the case of the ExecutorService implementation, the core implementation being returned by the call to Executors.newSingleThreadedExecutor() is a ThreadPoolExecutor.
The submit calls are provided by its parent AbstractExecutorService and all call execute internally. execute is overridden/provided by the ThreadPoolExecutor directly.
The full answer is a composition of two answers that were published here (plus a bit "extra"):
By submitting a task (vs. executing it) you get back a future which can be used to get the result or cancel the action. You don't have this kind of control when you execute (because its return type id void)
execute expects a Runnable while submit can take either a Runnable or a Callable as an argument (for more info about the difference between the two - see below).
execute bubbles up any unchecked-exceptions right away (it cannot throw checked exceptions!!!), while submit binds any kind of exception to the future that returns as a result, and only when you call future.get() a the (wrapped) exception will be thrown . The Throwable that you'll get is an instance of ExecutionException and if you'll call this object's getCause() it will return the original Throwable.
A few more (related) points:
Even if the task that you want to submit does not require returning a
result, you can still use Callable<Void> (instead of using a Runnable).
Cancellation of tasks can be done using the interrupt mechanism. Here's an example of how to implement a cancellation policy
To sum up, it's a better practice to use submit with a Callable (vs. execute with a Runnable). And I'll quote from "Java concurrency in practice" By Brian Goetz:
6.3.2 Result-bearing tasks: Callable and Future
The Executor framework uses Runnable as its basic task representation. Runnable is a fairly
limiting abstraction; run cannot return a value or throw checked
exceptions, although it can have side effects such as writing to a log
file or placing a result in a shared data structure. Many tasks are
effectively deferred computations—executing a database query, fetching
a resource over the network, or computing a complicated function. For
these types of tasks, Callable is a better abstraction: it expects
that the main entry point, call, will return a value and anticipates
that it might throw an exception.7 Executors includes several utility
methods for wrapping other types of tasks, including Runnable and
java.security.PrivilegedAction, with a Callable.
From the Javadoc:
The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.
So depending on the implementation of Executor you may find that the submitting thread blocks while the task is executing.
Just adding to the accepted answer-
However, exceptions thrown from tasks make it to the uncaught
exception handler only for tasks submitted with execute(); for tasks
submitted with submit() to the executor service, any thrown exception
is considered to be part of the task’s return status.
Source
I have the following Java code:
final Future future = exeService.submit(
new Runnable() {
public void run() {
myObject.doSomething();
}
}
);
future.get();
where exeService is an instance of
java.util.concurrent.ExecutorService
The problem is that myObject.doSomething() never returns, and, hence, future.get() never returns.
However, if I replace the call to submit with a call to execute like this:
exeService.execute(
new Runnable() {
public void run() {
myObject.doSomething();
}
}
);
the call to myObject.doSomething() does return. I don't know if it matters, but doSomething() is a void method.
Why is doSomething() finishing when using execute but not when using submit?
Also, I don't need to use Future.get(); that just seemed to be the most natural way of doing this. (I also run into the same problem with CountdownLatch.) The point is that I need to wait for doSomething() to finish before proceeding, and, for complicated reasons I won't go into here, I need to launch it on a separate thread. If there is another way of doing this that works, that would be fine.
As in Executor.execute() Javadoc:
Executes the given command at some
time in the future. The command may
execute in a new thread, in a pooled
thread, or in the calling thread, at
the discretion of the Executor
implementation.
So, the method execute() returns immediately leaving you with no option to query to status of submitted task.
On the other hand ExecutorService.submit():
Submits a Runnable task for execution
and returns a Future representing that
task. The Future's get method will
return null upon successful
completion.
The Future.get() will return only after successful competion, so never in your case.
This is further noted in Future.get() documentation:
Waits if necessary for the computation
to complete, and then retrieves its
result.
I created an SSCCE:
package com.stackoverflow.q2585971;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test {
public static void main(String args[]) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
Future<?> future = executor.submit(
new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Epic fail.");
}
}
}
);
System.out.println("Waiting for task to finish..");
future.get();
System.out.println("Task finished!");
executor.shutdown();
}
}
It works perfectly fine. It first prints
Waiting for task to finish..
then after one second you see
Task finished!
So, your problem lies somewhere else. I'll duplicate my comment on your question here:
Your question is pretty confusing. The first construct should just work. The confusion is in "returning". Don't you just mean "finishing" or "executing"? Your confusion seems to be based on the fact that future.get() actually waits for the runnable to be finished and thus will block the thread and prevent it from executing the remnant of the code after the future.get() line.
Java futures are blocking! get(). This method blocks the current thread until a future instance completes its work, thus requiring the use of one thread more than the work that must be performed just to manage what happens when it is done
Check for a deadlock(s) in doSomething.
I would start with searching for wait calls.
If you wait for something, you need to signal the object you are waiting for from the other thread by calling notify or notifyAll.