Android线程 异步 asynctask Looper MessageQueue handler
2015-11-07 13:55
483 查看
AsyncTask
知识点deque(双向队列)
BlockingQueue 线程池阻塞队列
AtomicInteger 线程安全计数
ThreadPoolExecutor 线程池实际执行类
SerialExecutor 确保顺序执行
3.0之前
同一时刻能够运行的线程数为5个,线程池总大小为128。也就是说当我们启动了10个任务时,只有5个任务能够立刻执行,另外的5个任务则需要等待,当有一个任务执行完毕后,第6个任务才会启动,以此类推。而线程池中最大能存放的线程数是128个,当我们尝试去添加第129个任务时,程序就会崩溃。
3.0之后
用了一个静态的serialExecutor,并且 里面的任务只能一个个的执行,当然也可以使用自定义线程池
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
SerialExecutor源码:(确保任务的先进先出)
private static class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); Runnable mActive; public synchronized void execute(final Runnable r) { mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { THREAD_POOL_EXECUTOR.execute(mActive); } } }
实际执行任务的类
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
线程通讯用的handler
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget();
handler
private static Handler getHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(); } return sHandler; } }
定义handler
private static class InternalHandler extends Handler { public InternalHandler() { super(Looper.getMainLooper()); } @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void handleMessage(Message msg) { AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } } }
获取UI线程的looper
/** Returns the application's main looper, which lives in the main thread of the application. */ public static Looper getMainLooper() { synchronized (Looper.class) { return sMainLooper; } }
ActivityThread中的main()函数:
public static void main(String[] args) { ... Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited") }
Looper
/** * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
子线程的prepare,从threadlocal获取,没有的话才创建Looper添加到threadlocal中去
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
Looper的构造器: 可以看到Looper里面有一个消息队列
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
获取当前线程的looper
/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); }
消息队列的轮询
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } msg.target.dispatchMessage(msg);//target是handler }
handler中的looper来自threadlocal
//handler构造方法 public Handler(Callback callback, boolean async) { ... mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
handler的方法 post(r),sendMessage(Msg)
post(r)也是将r转成msg之后sendMessageDelayed;最终都会进入队列
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this;//把msg的target指向handler自己 if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
相关文章推荐
- codeforces-559B-Equivalent Strings
- 解决 证书报 UUID 不匹配问题 Your build settings specify a provisioning profile with the UUID
- Android Studio运行工程报错:java.exe'' finished with non-zero exit value 1
- 核心动画(Core Animation)
- request获取网页单选框的值
- EasyUI学习笔记_3
- 【十一年】注入框架RoboGuice采用:(Your First Injection into a Custom View class)
- Duilib源码分析(四)绘制管理器—CPaintManagerUI—(前期准备三)
- UGUI 图片去色,取灰色
- iOS UIDatePicker使用
- play 集成squeryl ORM持久化框架
- [LintCode]Find Median of Unsorted Array O(n) quick sort
- Longest Consecutive Sequence 解答
- play2.0 集成 squeryl
- 触摸事件UITouch的用法
- UIButton内部子控件自定义布局-“UIEdgeInsets”
- 4.Arduino IDE代码如下
- UIBarButtonItemSystemItemFixedItem设定指定宽度的barButtonItem
- hdoj 2767 Proving Equivalences【强连通&&tarjan】
- IOS UISegmentedControl 分段控制器