小A打算跟大家分享内推赚取的佣金,只要通过小A内推成功,小A就会把内推的佣金跟推荐者平分喔。具体规则可以看文末
内推规则。悄悄告诉你,内推奖励金不低。
之前我们说过关于线程池的问题,我们可以用Executors的各种方法来获取不同的ThreadPoolExecutor来满足需求。但是当我们需要自定义线程池的时候需要注意些什么呢?
ThreadPoolExecutor的参数含义
ThreadPoolExecutor的构造方法有几个用的多的参数,它们的含义分别是· corePoolSize:线程池的基本大小· maximumPoolSize:当任务队列满时允许扩展到的线程池的线程数量· workQueue:存放任务队列的BlockingQueue· handler:当任务队列满时的处理策略
之前说过可以给AsyncTask指定线程池,我们用不同的参数构造线程池来验证效果。
LinkedBlockingQueue
public class DemoAsyncTask extends AsyncTask { private static final String TAG = "DemoAsyncTask"; private static BlockingQueue<Runnable> blockingQueue = new LinkedBlockingDeque<>(3); private static Executor threadPoolExecutor = new ThreadPoolExecutor(3, 3, 0, TimeUnit.MICROSECONDS, blockingQueue); @Override protected Object doInBackground(Object[] objects) { try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } Log.d(TAG, "doInBackground: num: " + objects[0]); return null; } public void demoExecute(String... params) { this.executeOnExecutor(threadPoolExecutor, params); }}
指定一个LinkedBlockingQueue给线程池,然后我们从外部调用,
for(int i = 0; i < 50; i ++) { new DemoAsyncTask().demoExecute(String.valueOf(i));}
这段代码运行就会崩溃,原因是
我们给线程池分配了50个任务,但是任务队列最大只能存放3个任务,当队列满时,系统会抛出RejectedExecutionException异常
解决这个问题有两种方法,一种是不给LinkedBlockingQueue指定队列大小。因为默认情况下 LinkedBlockingDeque会让队列不断增长以存放新进来的数据。这种方式能让50个任务正常进行。
另外一种是用 handler 参数指定队列满时的处理策略,代码可以改成下面这样
private static Executor threadPoolExecutor = new ThreadPoolExecutor(3, 3, 0, TimeUnit.MICROSECONDS, blockingQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
这是ThreadPoolExecutor的其中一个默认策略,我们直接看输出就明白了,
04-19 12:42:35.991 6167-6199/com.phoenix.mkdirdemo D/DemoAsyncTask: doInBackground: num: 204-19 12:42:35.991 6167-6198/com.phoenix.mkdirdemo D/DemoAsyncTask: doInBackground: num: 104-19 12:42:35.991 6167-6196/com.phoenix.mkdirdemo D/DemoAsyncTask: doInBackground: num: 004-19 12:42:36.991 6167-6199/com.phoenix.mkdirdemo D/DemoAsyncTask: doInBackground: num: 4704-19 12:42:36.991 6167-6198/com.phoenix.mkdirdemo D/DemoAsyncTask: doInBackground: num: 4804-19 12:42:36.991 6167-6196/com.phoenix.mkdirdemo D/DemoAsyncTask: doInBackground: num: 49
所以就是说,这个策略会把队列里老的请求丢弃,保留最新请求。因为一开始的任务0-2正在执行中,而队列已满,因此最终只能保留47-49最后三个请求。这个策略适合用在fast fail场景,快速的反馈给用户失败而不是让用户等待。
ArrayBlockingQueue
用 ArrayBlockingQueue会有个问题,因为它的存储方式是数组,需要一开始就指定大小,所以必须得指定 handler来做队列满时的处理策略。如果不指定handler的话只要任务数量超过 ArrayBlockingQueue 指定的大小,就会抛出 RejectedExecutionException异常。
回到 AsyncTask
其实 AynscTask 默认会有个线程池,这个线程池的大小是128,可以从源码看出来
private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);
所以如果用默认的AsyncTask来处理大量的任务的话是有可能导致应用崩溃的。
内推规则
· 只要把公众号发给想要找工作的朋友让朋友关注,然后把朋友的微信ID回复给小A,小A就会在成功推荐后联系你,然后在成功入职后跟你平分佣金。· 想找工作的朋友关注后点击面试 -> 内推,就可以免费获取内推机会。· 每推荐成功一个都会有奖励金哦!
