消息机制和线程池
消息机制
android的消息机制主要涉及以下几个类:
- Handler
- Looper
- prepare():对当前线程创建新的looper
- loop():循环当前线程中的消息
- quit():停止循环
- MessageQueue
- enqueueMessage():handler插入消息到消息队列中
- next():looper从消息队列中获取消息
- ThreadLocal:这个是在Looper里维护的
ThreadLocal有两种使用场景:
- 当作用域为线程,并且不同作用域需要有不同的数据副本的时候;
- 在复杂逻辑下对象需要不断传递的情况。
主线程已经被做成了是Looper的线程,所以不用像自己的线程那样做特殊处理。在ActivityThread
里的main()方法中:
创建自己的Looper 以及一个完整的实例:
package com.pan.learn;/*
* Copyright (C) 2016 Baidu, Inc. All Rights Reserved.
*/
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
/**
* Created by panhongchao on 16/2/12.
*/
public class HandlerActivity extends Activity {
public Handler mHandler;
private Handler handler1 = new Handler() {
@Override
public void handleMessage(Message msg) {
Toast.makeText(HandlerActivity.this, "handler1: " + Looper.myLooper(), Toast.LENGTH_SHORT).show();
}
};
private Handler handler2 = new Handler(createLooper("-sub-"), new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
Toast.makeText(HandlerActivity.this, "handler2: " + Looper.myLooper(), Toast.LENGTH_SHORT).show();
return true;
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button button = new Button(this);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message message = Message.obtain();
// handler1.sendMessage(message);
handler2.sendMessage(message);
}
});
new MThread().start();
setContentView(button);
}
public class MThread extends Thread {
@Override
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
Toast.makeText(HandlerActivity.this, "sub handler: " + Looper.myLooper(), Toast.LENGTH_SHORT)
.show();
}
};
Looper.loop();
}
}
private Looper createLooper(String threadName) {
final BlockingItem<Looper> bl = new BlockingItem<Looper>();
new Thread(threadName) {
@Override
public void run() {
Looper.prepare();
Looper l = Looper.myLooper();
bl.put(l);
Looper.loop();
}
}.start();
try {
return bl.take();
} catch (Exception e) {
return Looper.getMainLooper();
}
}
}
---------------------------------------------
/*
* Copyright (C) 2016 Baidu, Inc. All Rights Reserved.
*/
package com.pan.learn;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 一个线程安全的对象包装器。一般在多线程并发操作一个对象时使用。
* <p/>
* 注:BlockingItem使用了可重入锁ReentrantLock来处理资源的并发,默认是非公平的(先take的不一定先拿到)。
*
* @param <T> 需要被包装的对象类型
*/
public class BlockingItem<T> {
final Lock lock = new ReentrantLock();
final Condition notEmpty = lock.newCondition();
private volatile T item;
public void put(T x) {
lock.lock();
try {
item = x;
if (x != null) {
notEmpty.signal();
}
} finally {
lock.unlock();
}
}
public T take() throws InterruptedException {
lock.lock();
try {
while (item == null) {
notEmpty.await();
}
T t = item;
item = null;
return t;
} finally {
lock.unlock();
}
}
public T tryTake(long waitMs) throws InterruptedException {
lock.lock();
try {
while (item == null) {
if (!notEmpty.await(waitMs, TimeUnit.MILLISECONDS)) {
return null;
}
}
T t = item;
item = null;
return t;
} finally {
lock.unlock();
}
}
public T peek() {
return item;
}
}
线程和线程池
AsyncTask
- onPreExecute()
- doInBackground()
- onProgressUpdate()
- onPostExecute()
Task实例和execute()的创建和执行必须在主线程(错误)。----这个在子线程也是可以的。
小于1.6 AsyncTask是串行执行的;
大于等于1.6&&小于3.0 AsyncTask是并行执行的;
大于等于3.0 同时提供了串行并行的方法。
串行:execute
并行:executeOnExecutor
串行的实现是在内部实现了一个SerialExecutor
,把task在这里进行排队。
真正的执行是在由THREAD_POOL_EXECUTOR
线程池去执行的。
还有个InternalHandler
,它确保了线程能够从非主线程切回到主线程上去。【看代码它已经写死了线程为主线程,所以就保证了创建task不一定需要在主线程了,除非onPreExecute
中有UI上的操作】
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;
}
}
}
HandlerThread
一个在创建时已经有looper的thread。
IntentService
IntentService和Service的区别在于它在内部开启了一个子的线程,从而从UI线程独立出来了。
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
依赖HandlerThread建立了一个子线程,在子线程调用onHandleIntent
完成具体的业务逻辑。
java的并发框架(java executor framework)
- Executor:Executor接口是Executor框架中最基础的部分,定义了一个用于执行Runnable的execute方法
- ExecutorService:ExecutorService接口继承自Executor接口,定义了终止、提交任务、跟踪任务返回结果等方法。
- Callable:类似于Runnable的任务,区别在于它接受泛型,并且执行完成之后能够返回执行的结果。
- Future:异步任务的执行结果
- FutureTask:Futrue的具体实现类
- ThreadPoolExecutor:实现了ExecutorService接口的并且有线池的实现类。
- Executors:Executors中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。
线程池的处理流程是这样的:
- 首先线程池判断基本线程池是否已满?没满,创建一个工作线程来执行任务。满了,则进入下个流程。
- 其次线程池判断工作队列是否已满?没满,则将新提交的任务存储在工作队列里。满了,则进入下个流程。
- 最后线程池判断整个线程池是否已满?没满,则创建一个新的工作线程来执行任务,满了,则交给饱和策略来处理这个任务。