1. Android中的线程形态
Android中线程形态有3种:
- AsyncTask
- Handler
- IntentService
1.1 AsyncTask
轻量级异步任务类,底层实现: 线程池+Handler。
1.1.1 线程池参数
核心线程数量的策略:最少2个,最多4个,希望比CPU核心数量少1个,以避免CPU在后台工作时饱和。
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
1.1.2 Handler
Handler默认使用Looper.getMainLooper()进行初始化,所以可以在AsyncTask的“回调”方法中更新UI。
publishProgress() / postResult() 等通知方法都是使用Handler来发送Msg来实现线程切换。
1.2 HandlerThread
public class HandlerThread extends Thread {
...
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
// 线程安全
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
...
}
- HandlerThread继承自Thread,run方法内会创建Looper,并开启消息循环。
- HandlerThread的优势:初始化了Looper,并且提供了安全的getLooper()方法
1.3 IntentService
- 继承自Service的抽象类,适合执行后台任务,执行完会自动停止;
- 底层实现机制为HandlerThread,从onCreate方法可以看出;
- 在onHandleIntent()方法中实现业务逻辑
public abstract class IntentService extends Service {
...
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// 说明1
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
@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();
// 说明2
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
1.Service#onCreate()方法中创建HandlerThread、Handler;
2.Handler#handleMessage(msg)运行在子线程,内部调用抽象方法onHandleIntent(intent);
3.onHandleIntent(intent)结束后,调用销毁服务的方法stopSelf(msg.arg1);
4.所以IntentService不需要自己创建线程,不需要手动销毁服务。
2. 线程池
重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销;
有效控制线程池的最大并发数,避免大量线程之间相互抢占资源导致阻塞;
对线程管理,定时执行/周期间隔执行等待。
2.1 线程池常见参数
/**
* workQueue:工作队列,存储execute方法提交的runnable
* threadFactory:线程工厂,定义线程属性(优先级、守护线程等)
* handler: 当线程数量饱和、队列容量满了导致执行阻塞时的拒绝策略
**/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
2.2 常用5种线程池
核心线程不会被回收,非核心线程闲置时立即回收。
-
FixedThreadPool
固定数量的线程池,并且都是核心线程 -
CachedThreadPool
数量不定,只有非核心线程 -
ScheduledThreadPool
核心线程数量固定,非核心数量不定,非核心线程闲置时会被立即回收,用于执行定时/周期性任务 -
SingleThreadExecutor
只有一个核心线程 -
newWorkStealingPool(JDK1.8新增)
工作窃取线程池,通过ForkJoinPool实现,传入并发线程的数量
ThreadFactory的默认实现:Executors#DefaultThreadFactory
private static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
默认拒绝策略实现:ThreadPoolExecutor#AbortPolicy
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
2.3 自定义线程池
建议自定义线程池,不使用Executors提供的工厂方法。
限制corePoolSize大小;
限制maximumPoolSize大小;
不使用无界BlockingQueue。
ThreadPoolExecutor#execute(runnable)
1.线程数<corePoolSize,新建thread,并且start (corePoolSize)
2.线程数>=corePoolSize, 添加到等待队列workQueue,有空闲线程再执行 (workQueue.offer(command) BlockingQueue的size)
3.线程数>=corePoolSize,当等待队列workQueue已满,则再创建新线程执行 (BlockingQueue的size)
4.第3步基础上,创建线程失败,抛出异常 (maximumPoolSize)
关于corePoolSize的建议
- CPU密集型:(计算)CPU核心数+1
(即使当计算密集型的线程偶尔由于缺失故障或者其他原因而暂停时,这个额外的线程也能确保CPU的时钟周期不会被浪费)- IO密集型:(网络/磁盘IO)CPU核心数*2
- 混合型:(以上二者均有)