BackPort: Threads not under control

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

BackPort: Threads not under control

Srini Pillai
Hi all,

We are using the Concurrent package (backport) in a J2ee application
which spans several threads to connect with various other sources for
information. I was skeptical to use this package on a J2ee application
due to the popular notion that custom multithreading is not recommended
on J2ee apps. Some people convinced me that this package has more APIs
to control the Threads created.

Now coming to the real problem, below is the block of code I use to
start the various tasks and control them...

                ExecutorService service =
Executors.newCachedThreadPool();
                List futures = service.invokeAll(tasks, 20,
TimeUnit.SECONDS);
                Iterator futuresIter = futures.iterator();
                while (futuresIter.hasNext()) {
                    Future future = (Future) futuresIter.next();
                    try {
                          searchResults = future.get();
                    } catch(CancellationException ce) {
                        log.warn("Task timed out. Exception Message: "
+ ce);
                        future.cancel(true);
                    } catch(Exception e) {
                        log.warn("Exception occurred for a task.
Exception Message: " + e);
                        future.cancel(true);
                    }
                }
            }
            service.shutdownNow();
            System.out.println("SHUTDOWN ? " + service.isShutdown());
            .....


The 'tasks' that is called in the 'service.invoke()' are a list of
Callable implementations. When a Future task is timedout, as specified
in the invoke() method, control comes back to the exception but the
actual task still executes until it is terminated. The last stmt
(System.out) shows 'true', eventhough the task keeps executing until it
is dead. From the API declaration I believe the service tries to call
interrupt on this task but is it true that it cannot guarantee that the
task will stop and that shutdown will not always cause the task to stop
? Please advice. Also let me know if I am missing something... Really
appreciate your help...

Thanks,
Srini
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: BackPort: Threads not under control

Joe Bowbeer
Srini,

Strictly speaking, you want to call isTerminated instead of isShutdown
at the end, but I suspect it will also return true.

I suspect the source of your trouble is that the executing tasks are
not responding to interrupts.

invokeAll will cancel tardy tasks via task.cancel(true).  This will
set the task's state to cancelled and will also interrupt the task's
worker thread.  But the task's Callable/Runnable has to respond to the
interrupt (or at least the cancellation) in order for it to actually
stop.  Otherwise, if it ignores the interrupt, say, then it will run
to completion regardless.  The additional cancel(true) handling in
your code is probably wasted effort...


How to tell if a Callable is responsive to interrupts?

Check out the way the Callable<Integer> handles interrupt here:

http://java.sun.com/docs/books/tutorial/essential/threads/pool.html

    public Integer call() {
        for (int i = 0; i <= 100; i += 20) {
            //Perform some work...
            System.out.format("Worker number: %d, percent complete: %d%n",
                workerNumber, i);
            try {
                Thread.sleep((int)(Math.random() * 1000));
            } catch (InterruptedException e) {}
        }
        return(workerNumber);
    }

This is a *good* example of how *not* to respond to an interrupt :-(


To be responsive to interrupt, the task should be written as:

    public Integer call() {
        try {
            for (int i = 0; i <= 100; i += 20) {
                //Perform some work...
                System.out.format("Worker number: %d, percent complete: %d%n",
                    workerNumber, i);
                Thread.sleep((int)(Math.random() * 1000));
            }
        } catch (InterruptedException e) {}
        return(workerNumber);
    }


OR I prefer to simply declare the InterruptedException:

    public Integer call() throws InterruptedException {
        for (int i = 0; i <= 100; i += 20) {
            //Perform some work...
            System.out.format("Worker number: %d, percent complete: %d%n",
                workerNumber, i);
            Thread.sleep((int)(Math.random() * 1000));
        }
        return(workerNumber);
    }

--Joe


On 5/24/06, Srini Pillai <[hidden email]> wrote:

> Hi all,
>
> We are using the Concurrent package (backport) in a J2ee application
> which spans several threads to connect with various other sources for
> information. I was skeptical to use this package on a J2ee application
> due to the popular notion that custom multithreading is not recommended
> on J2ee apps. Some people convinced me that this package has more APIs
> to control the Threads created.
>
> Now coming to the real problem, below is the block of code I use to
> start the various tasks and control them...
>
>                 ExecutorService service =
> Executors.newCachedThreadPool();
>                 List futures = service.invokeAll(tasks, 20,
> TimeUnit.SECONDS);
>                 Iterator futuresIter = futures.iterator();
>                 while (futuresIter.hasNext()) {
>                     Future future = (Future) futuresIter.next();
>                     try {
>                           searchResults = future.get();
>                     } catch(CancellationException ce) {
>                         log.warn("Task timed out. Exception Message: "
> + ce);
>                         future.cancel(true);
>                     } catch(Exception e) {
>                         log.warn("Exception occurred for a task.
> Exception Message: " + e);
>                         future.cancel(true);
>                     }
>                 }
>             }
>             service.shutdownNow();
>             System.out.println("SHUTDOWN ? " + service.isShutdown());
>             .....
>
>
> The 'tasks' that is called in the 'service.invoke()' are a list of
> Callable implementations. When a Future task is timedout, as specified
> in the invoke() method, control comes back to the exception but the
> actual task still executes until it is terminated. The last stmt
> (System.out) shows 'true', eventhough the task keeps executing until it
> is dead. From the API declaration I believe the service tries to call
> interrupt on this task but is it true that it cannot guarantee that the
> task will stop and that shutdown will not always cause the task to stop
> ? Please advice. Also let me know if I am missing something... Really
> appreciate your help...
>
> Thanks,
> Srini

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: BackPort: Threads not under control

Srini Pillai
In reply to this post by Srini Pillai
Joe,

Thanks for the explaination. I found out that the task I was running
(which is an I/O operation, a socket connection) is not interrupted
properly. To respond to the interrupt call I had to place a dummy
Thread.sleep(1) in the loop that is performing the I/O to trap the
Interrupt. This throws the exception and stops the thread but I don't
like the idea of having the Thread.sleep() there... Is there a different
way to trap the interrupt ?

Thanks,
Srini

>>> "Joe Bowbeer" <[hidden email]> 5/24/2006 3:17 PM >>>
Srini,

Strictly speaking, you want to call isTerminated instead of isShutdown
at the end, but I suspect it will also return true.

I suspect the source of your trouble is that the executing tasks are
not responding to interrupts.

invokeAll will cancel tardy tasks via task.cancel(true).  This will
set the task's state to cancelled and will also interrupt the task's
worker thread.  But the task's Callable/Runnable has to respond to the
interrupt (or at least the cancellation) in order for it to actually
stop.  Otherwise, if it ignores the interrupt, say, then it will run
to completion regardless.  The additional cancel(true) handling in
your code is probably wasted effort...


How to tell if a Callable is responsive to interrupts?

Check out the way the Callable<Integer> handles interrupt here:

http://java.sun.com/docs/books/tutorial/essential/threads/pool.html 

    public Integer call() {
        for (int i = 0; i <= 100; i += 20) {
            //Perform some work...
            System.out.format("Worker number: %d, percent complete:
%d%n",
                workerNumber, i);
            try {
                Thread.sleep((int)(Math.random() * 1000));
            } catch (InterruptedException e) {}
        }
        return(workerNumber);
    }

This is a *good* example of how *not* to respond to an interrupt :-(


To be responsive to interrupt, the task should be written as:

    public Integer call() {
        try {
            for (int i = 0; i <= 100; i += 20) {
                //Perform some work...
                System.out.format("Worker number: %d, percent complete:
%d%n",
                    workerNumber, i);
                Thread.sleep((int)(Math.random() * 1000));
            }
        } catch (InterruptedException e) {}
        return(workerNumber);
    }


OR I prefer to simply declare the InterruptedException:

    public Integer call() throws InterruptedException {
        for (int i = 0; i <= 100; i += 20) {
            //Perform some work...
            System.out.format("Worker number: %d, percent complete:
%d%n",
                workerNumber, i);
            Thread.sleep((int)(Math.random() * 1000));
        }
        return(workerNumber);
    }

--Joe


On 5/24/06, Srini Pillai <[hidden email]> wrote:
> Hi all,
>
> We are using the Concurrent package (backport) in a J2ee application
> which spans several threads to connect with various other sources
for
> information. I was skeptical to use this package on a J2ee
application
> due to the popular notion that custom multithreading is not
recommended
> on J2ee apps. Some people convinced me that this package has more
APIs

> to control the Threads created.
>
> Now coming to the real problem, below is the block of code I use to
> start the various tasks and control them...
>
>                 ExecutorService service =
> Executors.newCachedThreadPool();
>                 List futures = service.invokeAll(tasks, 20,
> TimeUnit.SECONDS);
>                 Iterator futuresIter = futures.iterator();
>                 while (futuresIter.hasNext()) {
>                     Future future = (Future) futuresIter.next();
>                     try {
>                           searchResults = future.get();
>                     } catch(CancellationException ce) {
>                         log.warn("Task timed out. Exception Message:
"

> + ce);
>                         future.cancel(true);
>                     } catch(Exception e) {
>                         log.warn("Exception occurred for a task.
> Exception Message: " + e);
>                         future.cancel(true);
>                     }
>                 }
>             }
>             service.shutdownNow();
>             System.out.println("SHUTDOWN ? " +
service.isShutdown());
>             .....
>
>
> The 'tasks' that is called in the 'service.invoke()' are a list of
> Callable implementations. When a Future task is timedout, as
specified
> in the invoke() method, control comes back to the exception but the
> actual task still executes until it is terminated. The last stmt
> (System.out) shows 'true', eventhough the task keeps executing until
it
> is dead. From the API declaration I believe the service tries to
call
> interrupt on this task but is it true that it cannot guarantee that
the
> task will stop and that shutdown will not always cause the task to
stop
> ? Please advice. Also let me know if I am missing something...
Really
> appreciate your help...
>
> Thanks,
> Srini

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: BackPort: Threads not under control

Joe Bowbeer
In reply to this post by Srini Pillai
On 5/24/06, Srini Pillai <[hidden email]> wrote:
> Is there a different way to trap the interrupt?

  if (Thread.interrupted())
      throw new InterruptedException();


On 5/24/06, Srini Pillai <[hidden email]> wrote:

> Joe,
>
> Thanks for the explaination. I found out that the task I was running
> (which is an I/O operation, a socket connection) is not interrupted
> properly. To respond to the interrupt call I had to place a dummy
> Thread.sleep(1) in the loop that is performing the I/O to trap the
> Interrupt. This throws the exception and stops the thread but I don't
> like the idea of having the Thread.sleep() there... Is there a different
> way to trap the interrupt ?
>
> Thanks,
> Srini
>
> >>> "Joe Bowbeer" <[hidden email]> 5/24/2006 3:17 PM >>>
> Srini,
>
> Strictly speaking, you want to call isTerminated instead of isShutdown
> at the end, but I suspect it will also return true.
>
> I suspect the source of your trouble is that the executing tasks are
> not responding to interrupts.
>
> invokeAll will cancel tardy tasks via task.cancel(true).  This will
> set the task's state to cancelled and will also interrupt the task's
> worker thread.  But the task's Callable/Runnable has to respond to the
> interrupt (or at least the cancellation) in order for it to actually
> stop.  Otherwise, if it ignores the interrupt, say, then it will run
> to completion regardless.  The additional cancel(true) handling in
> your code is probably wasted effort...
>
>
> How to tell if a Callable is responsive to interrupts?
>
> Check out the way the Callable<Integer> handles interrupt here:
>
> http://java.sun.com/docs/books/tutorial/essential/threads/pool.html
>
>     public Integer call() {
>         for (int i = 0; i <= 100; i += 20) {
>             //Perform some work...
>             System.out.format("Worker number: %d, percent complete:
> %d%n",
>                 workerNumber, i);
>             try {
>                 Thread.sleep((int)(Math.random() * 1000));
>             } catch (InterruptedException e) {}
>         }
>         return(workerNumber);
>     }
>
> This is a *good* example of how *not* to respond to an interrupt :-(
>
>
> To be responsive to interrupt, the task should be written as:
>
>     public Integer call() {
>         try {
>             for (int i = 0; i <= 100; i += 20) {
>                 //Perform some work...
>                 System.out.format("Worker number: %d, percent complete:
> %d%n",
>                     workerNumber, i);
>                 Thread.sleep((int)(Math.random() * 1000));
>             }
>         } catch (InterruptedException e) {}
>         return(workerNumber);
>     }
>
>
> OR I prefer to simply declare the InterruptedException:
>
>     public Integer call() throws InterruptedException {
>         for (int i = 0; i <= 100; i += 20) {
>             //Perform some work...
>             System.out.format("Worker number: %d, percent complete:
> %d%n",
>                 workerNumber, i);
>             Thread.sleep((int)(Math.random() * 1000));
>         }
>         return(workerNumber);
>     }
>
> --Joe
>

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest