解决AsyncTask的线程池限制问题

这是一篇我个人在EOE发的帖子《解决AsyncTask的线程池限制问题》,由于eoe的blog系统实在是无言以对,我就把eoe上面的帖子以及blog是都转到csdn上来,原帖地址:http://www.eoeandroid.com/thread-329718-1-1.html


大家如果有使用到AsyncTask的话,应该会了解到AsyncTask固然好用,但是它本身设计了对于线程池的一些限制,如:
MAXIMUM_POOL_SIZE = 128;
CORE_POOL_SIZE = 5;
BlockingQueue sPoolWorkQueue =  new LinkedBlockingQueue(10);

这些限制就导致了,你在多线程操作的时候,线程最大数量为128+5+10 = 143,大家可以自己实验下,实际超过
早在去年使用的时候就查过对于这个限制的解析,也理解了,但是当时做的项目中远没有达到这么多的线程处理,所以也就没有深究,大家可以看下这篇文章,解析的很到位
http://www.linuxidc.com/Linux/2011-09/43150.htm

最近公司项目中,遇到批量添加 联系人数据的时候 数量超过143(实际测试数据为200,但是按上面的分析,应该是143)的时候,就会导致异常:
java.util.concurrent.RejectedExecutionException
网上查资料之后发现就是因为线程池的拒绝添加线程的问题,然后查看项目用到的线程操作,发现时用的CursorLoader  extends AsyncTaskLoader,AsyncTaskLoader中使用到了AsyncTask来处理多线程,这就是问题所在了
无奈,网上搜索资料查看解决方案,看到一篇文章解决这个问题的,http://www.cnblogs.com/fotransit/archive/2013/04/17/3025937.html
,他分析出这个问题之后,在初始化的时候,添加了一个对于线程池拒绝添加线程的一个策略,
/**
     * android源码
     */
    public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory,new ThreadPoolExecutor.DiscardOldestPolicy());

/**
     * 修改之后的
     */
    public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory,new ThreadPoolExecutor.DiscardOldestPolicy());

这样处理之后虽然可以保证不会报出RejectedExecutionException异常,但是如果你的线程数量超过 143,那你的143之后的线程是不会执行的,问题所在就是 BlockingQueue sPoolWorkQueue =  new LinkedBlockingQueue(10); 这个队列初始化的时候指定了队列的size()是10,就导致了线程数量的限制,查看下LinkedBlockingQueue的这个类,有一个构造函数 不传参数  Creates a LinkedBlockingQueue with a capacity of Integer.MAX_VALUE. ,把那个10去掉,OK了


Copy一份AsyncTask代码,然后修改一下两个地方,就可以解决这个问题了
public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory,new ThreadPoolExecutor.DiscardOldestPolicy());

BlockingQueue sPoolWorkQueue =  new LinkedBlockingQueue();

修改之后目前还没发生什么问题,有问题的,请及时反馈给我,如果分析有误,各位大牛请及时指出,我好修改,以免误人

最后感谢上面两个文章的博主

你可能感兴趣的:(Android开发)