2

Threads created by Async works for first time and the second time onwards they seems to be hanging. Here is how my code looks like -

Sprint Boot Rest service {
       -> invokes Class A @Async method {
                -> invokes Class B @Async method
       }
}

This rest service is processing a huge tree, resulting many threads.

Here is AsyncConfiguration looks like:

setCorePoolSize - 1000
setMaxPoolSize - 20000
setQueueCapacity - 5000
setThreadNamePrefix - "ABCService"

I am logging thread following thread number and right before first invocation everything looks clean . activeCount:0, poolSize:0, largestPoolSize:0, completedTaskCount:0, taskCount:0, remainingQueueCApacity:5000

While processing the first reuqest : activeCount:1000, poolSize:1000, largestPoolSize:1000, completedTaskCount:6, taskCount:1782, remainingQueueCApacity:4224

After processing first request: activeCount:0, poolSize:1000, largestPoolSize:1000, completedTaskCount:2595, taskCount:2595, remainingQueueCApacity:5000

After requesting my second request: activeCount:1000, poolSize:1000, largestPoolSize:1000, completedTaskCount:2595, taskCount:4915, remainingQueueCApacity:3680

I think threads are hanging because the threads seems to be not working. Also, I do not see any change in activeCount.

I have try/catch in Async methods to handle any exception.

Here are my Async method definitions looks like:

@Async
public void foo(String , String , list, String , boolean ){
    try {
            List<CompletableFuture<String>> completableFutureList
            for each item in list{
                CompletableFuture<String> response = ClassB.bar(String , String , item, String , boolean);
                completableFutureList.add(response);
            }

        CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[completableFutureList.size()])).join();

        .......
        ......
    } catch (Throwable e) {
        logger.error("Exception .... " );
    }
}


class B method

@Async
public CompletableFuture<String> bar(String , String , item, String , boolean)){
    try{
        .....
        ......
        }
    catch(......) {
    }
}   

Any help will be appreciated. Thanks.

update :

When I do thread dump, I see that all threads WAITING (parking) as shown below.

"ABCService-26" #83 prio=5 os_prio=0 tid=0x00007f2ab829b800 nid=0x716d waiting on condition [0x00007f272ffc7000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x0000000745cf3198> (a java.util.concurrent.CompletableFuture$Signaller) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.CompletableFuture$Signaller.block(CompletableFuture.java:1693) at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323) at java.util.concurrent.CompletableFuture.waitingGet(CompletableFuture.java:1729) at java.util.concurrent.CompletableFuture.join(CompletableFuture.java:1934) at com.abc.command.util.ClassA.foo(ClassA.java:106) at com.abc.command.util.ClassA.bar(ClassA.java:54) at com.abc.command.util.ClassA$$FastClassBySpringCGLIB$$b0eafa9.invoke() at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:115) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)

8
  • Post a template of class A and B please? Are those methods return void? Commented May 13, 2018 at 8:47
  • Hello Mạnh Quyết Nguyễn, Please check the post, I just added the methods... Thank you. Commented May 13, 2018 at 15:20
  • Where do you log those pool's properties? Inside Spring Boot service? Commented May 13, 2018 at 15:30
  • Yes. I save the ThreadPoolTaskExecutor instane to static variable in config class and use that variable in controller class to log the pool properties. Commented May 13, 2018 at 17:39
  • Are you loggin just after calling to A.foo? And your first request and second request is same right? Commented May 13, 2018 at 17:47

1 Answer 1

1

Issue seems to be JDK bug with CompletableFuture<String>. The workaround is using get(timeout) instead of join():

CompletableFuture<Void> future = CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[completableFutureList.size()]));

future.get(executionTime, TimeUnit.MILLISECONDS);

here are more details on the issue...

https://bugs.openjdk.java.net/browse/JDK-8201576 https://crondev.wordpress.com/2017/01/23/timeouts-with-java-8-completablefuture-youre-probably-doing-it-wrong/

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.