Cancelling a Callable implementation doesn't work correctly

467 views Asked by At

I began to immigrate to java thread pool instead of own my framework for pooling threads. So, I wrote a sample for this aim. Actually, the largest requirement is to stop the running thread if its execution is too late. In addition, to achieve this purpose, I use cancel method of Future class. In conclusion, the problem is the running thread after canceling it was not stopped and it's continuing to execute. My code is :

public class ThreadPoolWarmup
{
    static class CountDownClock1 implements Callable<Boolean>
    {
        public Boolean call() throws Exception
        {
            String threadName = Thread.currentThread().getName();
            long i = 0;
            for (; ; )
            {
                if ((i % 1000000000) == 0)
                    System.out.println(i + ", ");
                i++;
            }
        }
    }

    public static void main(String[] args)
    {
        Future<Boolean> f1 = null;
        try
        {
            ApplicationContext context = new ClassPathXmlApplicationContext("threadpool.xml");
            ThreadPoolTaskExecutor taskExecutor = (ThreadPoolTaskExecutor) context.getBean("taskExecutor");
            f1 = taskExecutor.submit(new CountDownClock1());
            Boolean b1 = f1.get(15,TimeUnit.SECONDS);
            System.out.println("Reslt is ===========>>>>> " +  b1);
        }
        catch (Exception t)
        {
            t.printStackTrace();
            boolean c1 = f1.cancel(true);
            System.out.println("Cancel result ======>>>>>>>>>  " + c1);
        }
    }
}

also the spring context (threadpool.xml) is:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
                       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd">

<bean id="taskExecutor"  class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="3" />
    <property name="maxPoolSize" value="3" />
    <property name="WaitForTasksToCompleteOnShutdown" value="true" />
    <property name="queueCapacity" value="-1"/>
    <property name="keepAliveSeconds" value="30"/>
</bean>

and when I run the program I get following the rerult:

0, 
1000000000, 
2000000000, 
3000000000, 
4000000000, 
5000000000, 
java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask.get(FutureTask.java:205)
    at thread.ThreadPoolWarmup.main(ThreadPoolWarmup.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Cancel result ======>>>>>>>>>  true
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
6000000000, 
7000000000, 
8000000000, 
9000000000, 
10000000000, 
11000000000, 
12000000000, 
13000000000, 
14000000000, 

(I didn't write all output because it's continuing forever.)

I told you my problem and I have another question: When I cancel the thread and stop it, the thread return to the thread pool and another task can be executed by that?

1

There are 1 answers

11
Kayaman On BEST ANSWER

Your task is simply uncancellable if already running, because the task doesn't perform anything to check whether the thread is interrupted.

If you make your loop into a while(!Thread.currentThread().isInterrupted()) the cancel(true) can try to interrupt the thread, which would then be noticed by the loop.

Using interruptible operations inside the task would also make it cancelable.