11.关于线程与线程池

1. Android中的线程形态

Android中线程形态有3种:

  1. AsyncTask
  2. Handler
  3. 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;
    }
	...
}
  1. HandlerThread继承自Thread,run方法内会创建Looper,并开启消息循环。
  2. 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种线程池

核心线程不会被回收,非核心线程闲置时立即回收。

  1. FixedThreadPool
    固定数量的线程池,并且都是核心线程

  2. CachedThreadPool
    数量不定,只有非核心线程

  3. ScheduledThreadPool
    核心线程数量固定,非核心数量不定,非核心线程闲置时会被立即回收,用于执行定时/周期性任务

  4. SingleThreadExecutor
    只有一个核心线程

  5. 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的建议

  1. CPU密集型:(计算)CPU核心数+1
    (即使当计算密集型的线程偶尔由于缺失故障或者其他原因而暂停时,这个额外的线程也能确保CPU的时钟周期不会被浪费)
  2. IO密集型:(网络/磁盘IO)CPU核心数*2
  3. 混合型:(以上二者均有)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值