网络访问频繁的项目---ThreadManager(线程池管理类)

一、先了解ThreadPoolExecutor这个类。

线程池ThreadPoolExecutor继承自ExecutorService.是jdk1.5加入的新特性,将提交执行的任务在内部线程池中的可用线程中执行。
构造函数
  
ThreadPoolExecutor(int corePoolSize, 
                              int maximumPoolSize, 
                              long keepAliveTime, 
                              TimeUnit unit, 
                              BlockingQueue<Runnable> workQueue, 
                              ThreadFactory threadFactory, 
                              RejectedExecutionHandler handler)

   (一)了解一个常用变量

                corePoolSize:线程池维护线程的最少数量.
                maximumPoolSize:线程池维护线程的最大数量
                keepAliveTime :线程池维护线程所允许的空闲时间
                unit:线程池维护线程所允许的空闲时间的单位
                workQueue: 线程池所使用的缓冲队列
                handler: 线程池对拒绝任务的处理策略
      一个任务通过 execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是Runnable类型对象的run()方法。
      当一个任务通过execute(Runnable)方法欲添加到线程池时:

      l  如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。

      l  如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。

      l  如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。

      l  如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

     l  当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。


ThreadPoolExecutor配置

一、ThreadPoolExcutor为一些Executor提供了基本的实现,这些Executor是由Executors中的工厂 newCahceThreadPool、newFixedThreadPool和newScheduledThreadExecutor返回的。 ThreadPoolExecutor是一个灵活的健壮的池实现,允许各种各样的用户定制。

二、线程的创建与销毁

1、核心池大小、最大池大小和存活时间共同管理着线程的创建与销毁。

2、核心池的大小是目标的大小;线程池的实现试图维护池的大小;即使没有任务执行,池的大小也等于核心池的大小,并直到工作队列充满前,池都不会创建更多的线程。如果当前池的大小超过了核心池的大小,线程池就会终止它。

3、最大池的大小是可同时活动的线程数的上限。

4、如果一个线程已经闲置的时间超过了存活时间,它将成为一个被回收的候选者。

5、newFixedThreadPool工厂为请求的池设置了核心池的大小和最大池的大小,而且池永远不会超时

6、newCacheThreadPool工厂将最大池的大小设置为Integer.MAX_VALUE,核心池的大小设置为0,超时设置为一分钟。这样创建了无限扩大的线程池,会在需求量减少的情况下减少线程数量。

三、管理

1、 ThreadPoolExecutor允许你提供一个BlockingQueue来持有等待执行的任务。任务排队有3种基本方法:无限队列、有限队列和同步移交。

2、 newFixedThreadPool和newSingleThreadExectuor默认使用的是一个无限的 LinkedBlockingQueue。如果所有的工作者线程都处于忙碌状态,任务会在队列中等候。如果任务持续快速到达,超过了它们被执行的速度,队列也会无限制地增加。稳妥的策略是使用有限队列,比如ArrayBlockingQueue或有限的LinkedBlockingQueue以及 PriorityBlockingQueue。

3、对于庞大或无限的池,可以使用SynchronousQueue,完全绕开队列,直接将任务由生产者交给工作者线程

4、可以使用PriorityBlockingQueue通过优先级安排任务


项目中一个线程池管理类,提供三个线程池

public class ThreadManager {
    public static final String DEFAULT_SINGLE_POOL_NAME = "DEFAULT_SINGLE_POOL_NAME";

    private static ThreadPoolProxy mLongPool = null;
    private static Object mLongLock = new Object();

    private static ThreadPoolProxy mShortPool = null;
    private static Object mShortLock = new Object();

    private static ThreadPoolProxy mDownloadPool = null;
    private static Object mDownloadLock = new Object();

    private static Map<String, ThreadPoolProxy> mMap = new HashMap<String, ThreadPoolProxy>();
    private static Object mSingleLock = new Object();

    // private static ThreadPoolProxy

    /** 获取下载线程 */
    public static ThreadPoolProxy getDownloadPool() {
        synchronized (mDownloadLock) {
            if (mDownloadPool == null) {
                mDownloadPool = new ThreadPoolProxy(3, 3, 5L);
            }
            return mDownloadPool;
        }
    }

    /**
     * 获取一个用于执行长耗时任务的线程池,避免和短耗时任务处在同一个队列 而阻塞了重要的短耗时的任务,通常用联网操作s
     */
    public static ThreadPoolProxy getLongPool() {
        synchronized (mLongLock) {
            if (mLongPool == null) {
                mLongPool = new ThreadPoolProxy(5, 5, 5L);
            }
            return mLongPool;
        }
    }

    /** 获取一个用于执行短耗时任务的线程池,避免因为和耗时长的任务处在同一个队列而长时间得不到执行,通常用来执行本地的IO/SQL */
    public static ThreadPoolProxy getShortPool() {
        synchronized (mShortLock) {
            if (mShortPool == null) {
                mShortPool = new ThreadPoolProxy(2, 2, 5L);
            }
            return mShortPool;
        }
    }

    /** 获取一个单线程池,所有任务将会被按照加入的顺序执行,免除了同步开销的问题 */
    public static ThreadPoolProxy getSinglePool() {
        return getSinglePool(DEFAULT_SINGLE_POOL_NAME);
    }

    /** 获取一个单线程池,所有任务将会被按照加入的顺序执行,免除了同步开销的问题 */
    public static ThreadPoolProxy getSinglePool(String name) {
        synchronized (mSingleLock) {
            ThreadPoolProxy singlePool = mMap.get(name);
            if (singlePool == null) {
                singlePool = new ThreadPoolProxy(1, 1, 5L);
                mMap.put(name, singlePool);
            }
            return singlePool;
        }
    }

    public static class ThreadPoolProxy {
        private ThreadPoolExecutor mPool;
        private int mCorePoolSize; //线程池维护线程的最少数量
        private int mMaximumPoolSize; //线程池维护线程的最大数量
        private long mKeepAliveTime; //线程池维护线程所允许的空闲时间

        private ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime) {
            mCorePoolSize = corePoolSize;
            maximumPoolSize = maximumPoolSize;
            mKeepAliveTime = keepAliveTime;
        }

        // 执行任务,当线程池处于关闭,将会重新创建的线程池
        public synchronized void execute(Runnable runn) {
            if (runn == null) {
                return;
            }
            if (mPool == null || mPool.isShutdown()) {
                // 参数说明
                // 当线程池中的线程小于mCorePoolSize,直接创建新的线程加入线程池执行任务
                // 当线程池中的线程数目等于mCorePoolSize,将会把任务放入任务队列BlockingQueue中
                // 当BlockingQueue中的任务放满了,将会创建新的线程去执行,
                // 但是当总线程数大于mMaximumPoolSize时,将会抛出异常,交给RejectedExecutionHandler处理
                // mKeepAliveTime是线程执行完任务后,且队列中没有可以执行的任务,存活的时间,后面的参数是时间单位
                // ThreadFactory是每次创建新的线程工厂
                mPool = new ThreadPoolExecutor(mCorePoolSize,//
                        mMaximumPoolSize, mKeepAliveTime,//
                        TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(),
                        Executors.defaultThreadFactory(), new AbortPolicy());
            }
            mPool.execute(runn);
        }

        /** 取消线程池中某个还未执行的任务 */
        public synchronized void cancel(Runnable runn) {
            if (mPool != null && (!mPool.isShutdown()) || mPool.isTerminating()) {
                mPool.getQueue().remove(runn);
            }
        }

        /** 取消线程池中某个还未执行的任务 */
        public synchronized boolean contains(Runnable runn) {
            if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {
                return mPool.getQueue().contains(runn);
            } else {
                return false;
            }
        }

        /** 立刻关闭线程池,并且正在执行的任务也将会被中断 */
        public void stop() {
            if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {
                mPool.shutdown();
            }
        }

        /** 平缓关闭单任务线程池,但是会确保所有已经加入的任务都将会被执行完毕才关闭 */
        public synchronized void shutdown() {
            if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {
                mPool.shutdownNow();
            }
        }
    }
}



展开阅读全文

没有更多推荐了,返回首页