Executors, Futures, and Cancelation

Discussion in 'Java' started by mievlecl@gmail.com, Dec 12, 2007.

  1. Guest

    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?
     
    , Dec 12, 2007
    #1
    1. Advertising

  2. Lew Guest

    wrote:
    > 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.

    --
    Lew
     
    Lew, Dec 12, 2007
    #2
    1. Advertising

  3. Guest

    On Dec 11, 9:01 pm, Lew <> wrote:
    > wrote:
    > > 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.
    >
    > --
    > 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
     
    , Dec 12, 2007
    #3
  4. Daniel Pitts Guest

    wrote:
    > On Dec 11, 9:01 pm, Lew <> wrote:
    >> wrote:
    >>> 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.
    >>
    >> --
    >> 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

    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.

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
     
    Daniel Pitts, Dec 12, 2007
    #4
  5. Mark Space Guest

    Daniel Pitts wrote:

    > 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, Dec 12, 2007
    #5
  6. Mark Space Guest

    Mark Space wrote:
    > Daniel Pitts wrote:
    >
    >> 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.


    Hmm, not to mention the presence of an isCanceled() method....
     
    Mark Space, Dec 12, 2007
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JJ
    Replies:
    1
    Views:
    528
    Steven Cheng[MSFT]
    Oct 15, 2007
  2. Andy B
    Replies:
    0
    Views:
    273
    Andy B
    Nov 26, 2007
  3. helaha
    Replies:
    26
    Views:
    1,418
  4. Pearson & prentice hall solutions
    Replies:
    0
    Views:
    1,176
    Pearson & prentice hall solutions
    Jul 24, 2009
  5. Oriane

    [Ajax Futures]Web part and UpdatePanel

    Oriane, Jan 7, 2008, in forum: ASP .Net Web Controls
    Replies:
    1
    Views:
    168
    Walter Wang [MSFT]
    Jan 8, 2008
Loading...

Share This Page