package com.netease.nim.uikit.common.framework; import android.annotation.TargetApi; import android.os.Build; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class NimTaskExecutor implements Executor { private final static int QUEUE_INIT_CAPACITY = 20; public static final Executor IMMEDIATE_EXECUTOR = new Executor() { @Override public void execute(Runnable command) { command.run(); } }; public static class Config { public int core; public int max; public int timeout; public boolean allowCoreTimeOut; public Config(int core, int max, int timeout, boolean allowCoreTimeOut) { this.core = core; this.max = max; this.timeout = timeout; this.allowCoreTimeOut = allowCoreTimeOut; } } private final String name; private final Config config; private ExecutorService service; public NimTaskExecutor(String name, Config config) { this(name, config, true); } public NimTaskExecutor(String name, Config config, boolean startup) { this.name = name; this.config = config; if (startup) { startup(); } } public void startup() { synchronized (this) { // has startup if (service != null && !service.isShutdown()) { return; } // create service = createExecutor(config); } } public void shutdown() { ExecutorService executor = null; synchronized (this) { // swap if (service != null) { executor = service; service = null; } } if (executor != null) { // shutdown if (!executor.isShutdown()) { executor.shutdown(); } // recycle executor = null; } } @Override public void execute(Runnable runnable) { synchronized (this) { // has shutdown, reject if (service == null || service.isShutdown()) { return; } // execute service.execute(runnable); } } public Future<?> submit(Runnable runnable) { synchronized (this) { if (service == null || service.isShutdown()) { return null; } return service.submit(runnable); } } private ExecutorService createExecutor(Config config) { ThreadPoolExecutor service = new ThreadPoolExecutor(config.core, config.max, config.timeout, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(QUEUE_INIT_CAPACITY), new TaskThreadFactory(name), new ThreadPoolExecutor.DiscardPolicy()); allowCoreThreadTimeOut(service, config.allowCoreTimeOut); return service; } static class TaskThreadFactory implements ThreadFactory { private final ThreadGroup mThreadGroup; private final AtomicInteger mThreadNumber = new AtomicInteger(1); private final String mNamePrefix; TaskThreadFactory(String name) { SecurityManager s = System.getSecurityManager(); mThreadGroup = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); mNamePrefix = name + "#"; } public Thread newThread(Runnable r) { Thread t = new Thread(mThreadGroup, r, mNamePrefix + mThreadNumber.getAndIncrement(), 0); // no daemon if (t.isDaemon()) t.setDaemon(false); // normal priority if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } } private static final void allowCoreThreadTimeOut(ThreadPoolExecutor service, boolean value) { if (Build.VERSION.SDK_INT >= 9) { allowCoreThreadTimeOut9(service, value); } } @TargetApi(9) private static final void allowCoreThreadTimeOut9(ThreadPoolExecutor service, boolean value) { service.allowCoreThreadTimeOut(value); } }