Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / December 2007

Tip: Looking for answers? Try searching our database.

Executors, Futures, and Cancelation

Thread view: 
mievlecl@gmail.com - 12 Dec 2007 03:53 GMT
Hello.  I am working with the java.util.concurrent API introduced in
Java 1.5.  Specifically, I will talk about Executors, ExecutorServices
and Futures.

So far, I have gotten a lot of use out of the API, and used it on a
number of projects.  However, I am consistently running into a problem
for which I have not found a good solution.

Callables submitted to an ExecutorService return a reference to a
Future object.  This future object gives you some modest ways to
interact with the task: a method to cancel the task (cancel), methods
to query the status of the task (isDone/isCancelled), and methods to
get the result of the task's processing (get).

The problem is as follows:

Say you wish to cancel some long-running task that you know is queued
for execution.  Let's say you do this with, say:

future.cancel(true); // true allows the executor to use an interrupt
to help cancel the task

The trouble here, is, now that we have cancelled the task, we have no
way of determining if the task was cancelled before running, or if it
was cancelled while running.

Let us say that there's something we always need to do after this
task.  Let's call "something" a method: "myCleanup()".

By "after this task," I mean we always need to this "myCleanup()"
whether the task ran to completion or was cancelled.  So, there should
be a one-to-one relationships between enqueues of the task, and calls
to "myCleanup()".

For the sake of serial execution, we put the call to "myCleanup()" in
the task code itself.  So the core of the task code looks something
like:

performWhateverThisTaskDoes();
cleanup();

However, it is possible that the call to --

future.cancel(true);

-- will prevent this task from ever being executed.  This is
especially true if, for example, our executor has a sizable task
backlog in its work queue.  That's OK.  We asked for the task to be
cancelled, and we got it.

The trouble comes when you realize (or already know) that --

future.cancel(true);

-- does not always stop the task from executing.  If the task is "in
the process of executing," cancelling it will actually normally do
nothing -- the task will happily run to completion.  This is OK and I
have come to terms with this behavior.

The crux of the problem is there's no way to figure out what happened
-- what state the task as in, when it was cancelled.  I have no idea
if I should expect that the task is "in progress" and will eventually
call myCleanup() for me, or if it is still "in queue," and will never
execute, because it's been cancelled before any executor even set eyes
on it.

Assume, for example purposes, that because of the nature of the
myCleanup() method, it is undesirable or incorrect to call it twice
per task enqueued.

This leaves me in a tricky spot:  I've cancelled the task, but I have
no way of knowing if the task was cancelled "pre-execution" or "mid-
execution."  It's important for me to know, so that I can know whether
"myCleanup()" needs to be called manually, or if it will be handled by
the task.

To me, it seems a fairly natural thing to be able to cancel tasks.  It
also seems like a fairly useful piece of information to know if that
task was cancelled before beginning, or was cancelled while running --
since the two scenarios can leave the software in very different
states.  Yet, as far as I can see, there is no way to determine this
information.

You may suggest to me the isDone/isCancelled Future API methods.
Please note that there is actually no way to determine whether a task
actually ran or was cancelled before running by using the information
retrieved from these methods.  Nor is the return value from
Future.cancel() informative in these situations.

I have also tried extending FutureTask and overriding #done().  This
method is not called if your task is cancelled before execution.  As
is it is not possible to efficiently respond to the "absence" of a
method call, this is not a very good way to determine if a task will
or will not run.

Any ideas?
Lew - 12 Dec 2007 04:01 GMT
> Hello.  I am working with the java.util.concurrent API introduced in
> Java 1.5.  Specifically, I will talk about Executors, ExecutorServices
> and Futures.

This is a bit complex of a topic, but it's thoroughly handled in the book
/Java Concurrency in Practice/, by Brian Goetz et al.  Buy it, study it.

Signature

Lew

mievlecl@gmail.com - 12 Dec 2007 04:08 GMT
> mievl...@gmail.com wrote:
> > Hello.  I am working with the java.util.concurrent API introduced in
[quoted text clipped - 6 lines]
> --
> Lew

Thanks for the reply.  I actually own this book, and have been telling
my co-workers about it almost daily.  It's also sitting open on my
desk right now.  To be honest, I thought I had gleaned most that I
could be from it; however, I may well be missing something.  A re-read
wouldn't hurt me, so I think I will.  But I am still interested in
hearing others' first-hand experience with such issues.

thanks,

Mike
Daniel Pitts - 12 Dec 2007 18:22 GMT
>> mievl...@gmail.com wrote:
>>> Hello.  I am working with the java.util.concurrent API introduced in
[quoted text clipped - 16 lines]
>
> Mike
Its kind of funny you should bring this up now, a coworker of mine is in
the same situation.

My suggestion to him was that he might be able to "not care" if the task
had started yet. It's mostly an IO bound loop that would be interrupted,
and we wouldn't care after that point.

If you're process dictates that you know what has started, etc... I
would suggest passing to your Callable objects something that they can
manipulate to give feedback on their state (started, not started,
successfully canceled, etc...).  This isn't a trivial task, but it isn't
insurmountable either.  You'll have to make sure you do proper analysis
on the concurrent code that access this object.
Also note that Future.cancel will return a boolean value whether it
succeeds in canceling or not.
<http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Future.html#cancel(
boolean
)>

Hopefully, this helps you.

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Mark Space - 12 Dec 2007 22:46 GMT
> Also note that Future.cancel will return a boolean value whether it
> succeeds in canceling or not.

I've never used the Future object, but I notice the API says that get()
and get( timeout, timeunit) return a CanceledException if the task has
been canceled.  The latter version of get could be used with a short
timeout to test is a Future object belongs to a task that got canceled.
Mark Space - 12 Dec 2007 22:52 GMT
>> Also note that Future.cancel will return a boolean value whether it
>> succeeds in canceling or not.
[quoted text clipped - 3 lines]
> been canceled.  The latter version of get could be used with a short
> timeout to test is a Future object belongs to a task that got canceled.

Hmm, not to mention the presence of an isCanceled() method....


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.