package in.srain.cube.image.impl; import android.annotation.TargetApi; import android.os.Build; import in.srain.cube.concurrent.LinkedBlockingDeque; import in.srain.cube.image.ImageLoader.ImageTaskOrder; import in.srain.cube.image.iface.ImageTaskExecutor; import in.srain.cube.util.Version; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * Use a Thread pool to manager the thread. * * @author http://www.liaohuqiu.net */ public class DefaultImageTaskExecutor implements ImageTaskExecutor { private static final TimeUnit KEEP_ALIVE_TIME_UNIT; private static final int KEEP_ALIVE_TIME = 1; private static int sNUMBER_OF_CORES = Runtime.getRuntime().availableProcessors(); private static DefaultImageTaskExecutor sInstance = null; private final ThreadPoolExecutor mThreadPool; private final LinkedBlockingStack<Runnable> mTaskWorkQueue; static { KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS; sInstance = new DefaultImageTaskExecutor(); } public static DefaultImageTaskExecutor getInstance() { return sInstance; } public static class LinkedBlockingStack<T> extends LinkedBlockingDeque<T> { private static final long serialVersionUID = -4114786347960826192L; private ImageTaskOrder mImageTaskOrder = ImageTaskOrder.FIRST_IN_FIRST_OUT; public void setTaskOrder(ImageTaskOrder order) { mImageTaskOrder = order; } @Override public boolean offer(T e) { if (mImageTaskOrder == ImageTaskOrder.LAST_IN_FIRST_OUT) { return super.offerFirst(e); } else { return super.offer(e); } } @Override public T remove() { if (mImageTaskOrder == ImageTaskOrder.LAST_IN_FIRST_OUT) { return super.removeFirst(); } else { return super.remove(); } } } @TargetApi(Build.VERSION_CODES.GINGERBREAD) private DefaultImageTaskExecutor() { mTaskWorkQueue = new LinkedBlockingStack<Runnable>(); mThreadPool = new ThreadPoolExecutor(sNUMBER_OF_CORES, sNUMBER_OF_CORES, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT, mTaskWorkQueue, new DefaultThreadFactory()); if (Version.hasGingerbread()) { mThreadPool.allowCoreThreadTimeOut(true); } else { // Does nothing } } /** * The default thread factory */ static class DefaultThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1); private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; private static final String sPre = "image-executor-pool-"; private static final String sPost = "-thread-"; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = sPre + poolNumber.getAndIncrement() + sPost; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon()) t.setDaemon(false); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } } @Override public void execute(Runnable command) { mThreadPool.execute(command); } @Override public void setTaskOrder(ImageTaskOrder order) { mTaskWorkQueue.setTaskOrder(order); } }