newCachedThreadPool的线程池特点:

(1)它是一个可以无限扩大的线程池;它比较适合处理执行时间比较小的任务;corePoolSize为0,maximumPoolSize为无限大,意味着线程数量可以无限大;keepAliveTime为60S,意味着线程空闲时间超过60S就会被杀死;采用SynchronousQueue装等待的任务,这个阻塞队列没有存储空间,这意味着只要有请求到来,就必须要找到一条工作线程处理他,如果当前没有空闲的线程,那么就会再创建一条新的线程。

(2)如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
可以看出该线程池会复用空闲的线程,从而减少创建对象和回收对象带来开销。

项目中用到了newCachedThreadPool,查了一下,为啥用这个:

  private static final Logger LOGGER = LoggerFactory.getLogger(AbstractCityAsyncClient.class);

    private static final int QUEUE_SIZE = 10000;

    private static final int WORKER_COUNT = 8;

    private static final ThreadGroup THREAD_GROUP = new ThreadGroup("cityAsyncClientThrceadGroup");

    private static final ExecutorService EXECUTOR_SERVICE = Executors.newCachedThreadPool(new ThreadFactory() {

        private final AtomicInteger threadNumber = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(THREAD_GROUP, r, "cityAsyncClient-thread-pool-" + threadNumber.getAndIncrement());
        }
    });

 @Override
    public void asyncExecRequest(CityRequest cityRequest) {
        String name = cityRequest.getName();
        BlockingQueue<CityRequest> blockingQueue = requestQueueMap.get(name);
        if (blockingQueue == null) {
            synchronized (requestQueueMap) {
                /* double check */
                blockingQueue = requestQueueMap.get(name);
                if (blockingQueue == null) {
                    blockingQueue = new ArrayBlockingQueue<>(QUEUE_SIZE);
                    requestQueueMap.put(name, blockingQueue);

                    for (int i = 0; i < WORKER_COUNT; i++) {
                        EXECUTOR_SERVICE.execute(new Worker(this, blockingQueue));
                    }
                }
            }
        }

        try {
            if (!blockingQueue.offer(cityRequest, 10L, TimeUnit.MILLISECONDS)) {
                execRequest(cityRequest);
            }
        } catch (InterruptedException e) {
            LOGGER.error("{}.asyncExecRequest error.", this.getClass().getSimpleName(), e);
        }
    }

之所以要用到newCachedThreadPool的原因是:

主要是考虑到了(a)如果线程池超过长度,可以灵活回收空闲线程,若无可回收,则新建线程,。因为车辆定位信息可能有时候多,有时候少,考虑到复用性的问题,如果线程闲置的话,可以复用。减少损耗系统资源。

(b )它比较适合处理执行时间比较小的任务;我们的任务到了一定上线就会及时处理。(数量1000,等待时间 5000毫秒,也就是说,不管数据过来多少,只要到了1000条或者5秒就发送)