All the thread of pool are WAITING (parking)

1.3k views Asked by At

I used a thread pool like this: new ThreadPoolExecutor(8, 8, 8, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(2048)); Run it and submit tasks in parallel for a while, then use FutureTask to get the result. It seems normal at the beginning, but all of the 8 threads of the pool become WAITING (parking) state very soon. No any one thread could be running again and the task queue become more and more longer. I look at the FutureTask.awaitDone() briefly, I think maybe it's the last line code LockSupport.park(this) cause this state. So, what should I do to avoid the state for these threads?

Actual codes(Project based on SpringBoot):

public class MyAsyncConfigurerSupport extends AsyncConfigurerSupport {

    @Bean
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(8);
        executor.setMaxPoolSize(8);
        executor.setKeepAliveSeconds(8);
        executor.setQueueCapacity(2048);
        executor.setAllowCoreThreadTimeOut(true);
        executor.setRejectedExecutionHandler((Runnable r, ThreadPoolExecutor exe) -> {
            throw new RuntimeException("TooBusy");
        });
        return executor;
    }
}
public class MyController {

    @Autowired
    private MyService service;

    public String get(String key) {
        Future<String> future = service.getSomeThing(key);
        // numbers of same kind of futures
        return future.get();
    }
}
@Service
public class MyService {
    @Async
    public Future<String> getSomeThing(String key) {
        // Call remote http server
        String result = feignClient.callAPI(key);
        return new AsyncResult<>(result);
    }
}

Another kind of deadlock endless loop (fixed on new version of jdk, replaced with a Recursive update Exception):

    Map<String, Object> concurrentMap = new ConcurrentHashMap<>();
    concurrentMap.computeIfAbsent("ABC", k -> {
        Object obj = new Object();
        concurrentMap.put("ABC", obj);
        return obj;
    });
1

There are 1 answers

0
wangkui On

Sorry guys, because my project is huge, so the actual codes above (which I think is the actual codes almost) is not the real actual codes. Now I find out the primary cause and these simple codes following could reproduce it.

public static void main(String[] args) {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(4);
    executor.setMaxPoolSize(4);
    executor.setKeepAliveSeconds(4);
    executor.setQueueCapacity(1024);
    executor.setBeanName("AA");
    executor.setRejectedExecutionHandler((Runnable r, ThreadPoolExecutor exe) -> {
        throw new RuntimeException("TooBusy");
    });
    executor.initialize();

    for (int i = 0; i < 4; i++) {
        executor.execute(() -> {
            Future<Long> f = executor.submit(System::currentTimeMillis);
            try {
                f.get();
            } catch (Exception e) {
            }
        });
    }
}

Just because there has nestification of async execute. The 1st level tasks used all of the threads, then the 2nd level tasks have no chance to be executed, but the 1st level tasks are waiting for the results of 2nd level tasks, so, all of them are WAITING (parking)