package com.sohu.cache.async.impl; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.async.KeyFuture; import com.sohu.cache.async.NamedThreadFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.*; /** * Created by yijunzhang on 14-6-18. */ public class AsyncServiceImpl implements AsyncService { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final int WARNING_TIMEOUT = 2000; private final int INTERRUPT_TIMEOUT = 10000; private final String DEFAULT_THREAD_POOL = "default_thread_pool"; private final ExecutorService defaultThreadPool; private final ThreadPoolExecutor observeFuturePool; public ConcurrentMap<String, ExecutorService> threadPoolMap; private final BlockingQueue<KeyFuture<?>> futureQueue; public AsyncServiceImpl() { defaultThreadPool = new ThreadPoolExecutor(256, 256, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(), new NamedThreadFactory("async", true)); observeFuturePool = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(), new NamedThreadFactory("future-observe", true)); threadPoolMap = new ConcurrentSkipListMap<String, ExecutorService>(); futureQueue = new LinkedBlockingQueue<KeyFuture<?>>(); threadPoolMap.put(DEFAULT_THREAD_POOL, defaultThreadPool); startObserveFuture(); } private final Runnable observeTask = new Runnable() { @Override public void run() { while (true) { try { KeyFuture<?> keyFuture = futureQueue.take(); String key = keyFuture.getKey(); Future<?> future = keyFuture.getFuture(); try { long begin = System.currentTimeMillis(); future.get(INTERRUPT_TIMEOUT, TimeUnit.MILLISECONDS); long costTime = System.currentTimeMillis() - begin; if (costTime >= WARNING_TIMEOUT) { logger.warn("WARNING:future={} costTime={}", key, costTime); } else { logger.info("future={} costTime={}", key, costTime); } } catch (TimeoutException te) { logger.error("ERROR:Timeout:future={},costTime={}", key, INTERRUPT_TIMEOUT); } catch (Exception e) { logger.error(e.getMessage(), e); } } catch (Exception e) { logger.error(e.getMessage(), e); } } } }; private void startObserveFuture() { observeFuturePool.execute(observeTask); observeFuturePool.execute(observeTask); } @Override public boolean submitFuture(KeyCallable<?> callable) { return submitFuture(DEFAULT_THREAD_POOL, callable); } @Override public boolean submitFuture(String threadPoolKey, KeyCallable<?> callable) { try { Future<?> future = getExecutorService(threadPoolKey).submit(callable); //忽略queue溢出 futureQueue.put(new KeyFuture(callable.getKey(), future)); return true; } catch (Exception e) { logger.error(e.getMessage() + callable.getKey(), e); return false; } } @Override public Future<?> submitFuture(Callable<?> callable) { try { Future<?> future = defaultThreadPool.submit(callable); //忽略queue溢出 futureQueue.put(new KeyFuture(callable.getClass().getName(), future)); return future; } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } private ExecutorService getExecutorService(String key) { return threadPoolMap.get(key); } @Override public void assemblePool(String threadPoolKey, ThreadPoolExecutor threadPool) { ExecutorService executorService = threadPoolMap.putIfAbsent(threadPoolKey, threadPool); if (executorService != null) { logger.error("{} is assembled", threadPoolKey); } } public void destory() { for (ExecutorService executorService : threadPoolMap.values()) { if (!executorService.isShutdown()) { executorService.shutdown(); } } threadPoolMap.clear(); } }