Android的线程和线程池

lbbk4462 7年前
   <p>线程在Android中是一个很重要的概念,从用途上来说,线程分为主线程和子线程,主线程主要处理和界面相关的事情,而子线程则往往用于执行耗时操作。在Android中扮演线程角色的还有很多,比如AsyncTask和IntentService,同时HandlerThread也是一种特殊的线程,但他们本质都是传统的线程。AsyncTask底层用到了线程池,对于IntentService和HandlerThread来说,它们的底层则直接使用了线程。</p>    <p>不同形式的线程虽然都是线程,但是它们具有不同的特性和使用场景。AsyncTask封装了线程池和Handler,它主要是为了方便开发者在子线程中更新UI,HandlerThread是一中消息循环的线程,在它的内部可以使用Handler。IntentService是一个服务,系统对其进行了封装使其可以更方便地执行后台任务,IntentService内部采用HandlerThread来执行任务,当任务执行完毕后IntentService会自动退出。</p>    <p>在操作系统中,线程是操作系统的调度的最小单元,同时线程又是一种受限的系统资源,即线程不可能无限制地产生,并且线程的创建和销毁都会相应的开销。如果一个进程中频繁地创建和销毁线程,这显然不是高效的做法,正确的做法是采用线程池,在这个线程池中会缓存一定数量的线程,通过线程池就可以避免因为频繁创建和销毁线程所带来的系统开销。</p>    <h3>Android中的线程形态</h3>    <p>AsyncTask</p>    <p>AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI。从实现上来说,AsyncTask封装了Thread和Handler,通过AsyncTask可以更加方便地执行后台任务以及在主线程中访问UI,但是AsyncTask并不适合进行特别耗时的后台任务,对于特别耗时的任务来说,用线程池比较好点。</p>    <p>AsyncTask提供了4个核心方法:</p>    <ul>     <li>onPreExecute(),在主线程中执行,在异步任务执行之前,次方法会被调用,做一些准备工作。</li>     <li>doInBackground(Params…params),在线程池中执行,次方法用于执行异步任务,params参数表示异步任务的输入参数。</li>     <li>onProgressUpdate(Progress…values),在主线程中执行,当后台任务的执行进度发生改变时此方法会被调用。</li>     <li>onPostExecute(Result result),在主线程中执行,在异步任务执行之后,此方法会被调用。</li>    </ul>    <p>看下源码:</p>    <pre>  <code class="language-java">public abstract class AsyncTask<Params, Progress, Result> {      private static final String LOG_TAG = "AsyncTask";        private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();      // We want at least 2 threads and at most 4 threads in the core pool,      // preferring to have 1 less than the CPU count to avoid saturating      // the CPU with background work      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 ThreadFactory sThreadFactory = new ThreadFactory() {          private final AtomicInteger mCount = new AtomicInteger(1);            public Thread newThread(Runnable r) {              return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());          }      };        private static final BlockingQueue<Runnable> sPoolWorkQueue =              new LinkedBlockingQueue<Runnable>(128);        /**       * An {@link Executor} that can be used to execute tasks in parallel.       */      public static final Executor THREAD_POOL_EXECUTOR;        static {          ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(                  CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,                  sPoolWorkQueue, sThreadFactory);          threadPoolExecutor.allowCoreThreadTimeOut(true);          THREAD_POOL_EXECUTOR = threadPoolExecutor;      }        /**       * An {@link Executor} that executes tasks one at a time in serial       * order.  This serialization is global to a particular process.       */      public static final Executor SERIAL_EXECUTOR = new SerialExecutor();        private static final int MESSAGE_POST_RESULT = 0x1;      private static final int MESSAGE_POST_PROGRESS = 0x2;        private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;      private static InternalHandler sHandler;        private final WorkerRunnable<Params, Result> mWorker;      private final FutureTask<Result> mFuture;        private volatile Status mStatus = Status.PENDING;        private final AtomicBoolean mCancelled = new AtomicBoolean();      private final AtomicBoolean mTaskInvoked = new AtomicBoolean();        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);              }          }      }        /**       * Indicates the current status of the task. Each status will be set only once       * during the lifetime of a task.       */      public enum Status {          /**           * Indicates that the task has not been executed yet.           */          PENDING,          /**           * Indicates that the task is running.           */          RUNNING,          /**           * Indicates that {@link AsyncTask#onPostExecute} has finished.           */          FINISHED,      }        private static Handler getHandler() {          synchronized (AsyncTask.class) {              if (sHandler == null) {                  sHandler = new InternalHandler();              }              return sHandler;          }      }        /** @hide */      public static void setDefaultExecutor(Executor exec) {          sDefaultExecutor = exec;      }        /**       * Creates a new asynchronous task. This constructor must be invoked on the UI thread.       */      public AsyncTask() {          mWorker = new WorkerRunnable<Params, Result>() {              public Result call() throws Exception {                  mTaskInvoked.set(true);                  Result result = null;                  try {                      Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                      //noinspection unchecked                      result = doInBackground(mParams);                      Binder.flushPendingCommands();                  } catch (Throwable tr) {                      mCancelled.set(true);                      throw tr;                  } finally {                      postResult(result);                  }                  return result;              }          };            mFuture = new FutureTask<Result>(mWorker) {              @Override              protected void done() {                  try {                      postResultIfNotInvoked(get());                  } catch (InterruptedException e) {                      android.util.Log.w(LOG_TAG, e);                  } catch (ExecutionException e) {                      throw new RuntimeException("An error occurred while executing doInBackground()",                              e.getCause());                  } catch (CancellationException e) {                      postResultIfNotInvoked(null);                  }              }          };      }        private void postResultIfNotInvoked(Result result) {          final boolean wasTaskInvoked = mTaskInvoked.get();          if (!wasTaskInvoked) {              postResult(result);          }      }        private Result postResult(Result result) {          @SuppressWarnings("unchecked")          Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,                  new AsyncTaskResult<Result>(this, result));          message.sendToTarget();          return result;      }        /**       * Returns the current status of this task.       *       * @return The current status.       */      public final Status getStatus() {          return mStatus;      }        /**       * Override this method to perform a computation on a background thread. The       * specified parameters are the parameters passed to {@link #execute}       * by the caller of this task.       *       * This method can call {@link #publishProgress} to publish updates       * on the UI thread.       *       * @param params The parameters of the task.       *       * @return A result, defined by the subclass of this task.       *       * @see #onPreExecute()       * @see #onPostExecute       * @see #publishProgress       */      @WorkerThread      protected abstract Result doInBackground(Params... params);        /**       * Runs on the UI thread before {@link #doInBackground}.       *       * @see #onPostExecute       * @see #doInBackground       */      @MainThread      protected void onPreExecute() {      }        /**       * <p>Runs on the UI thread after {@link #doInBackground}. The       * specified result is the value returned by {@link #doInBackground}.</p>       *        * <p>This method won't be invoked if the task was cancelled.</p>       *       * @param result The result of the operation computed by {@link #doInBackground}.       *       * @see #onPreExecute       * @see #doInBackground       * @see #onCancelled(Object)        */      @SuppressWarnings({"UnusedDeclaration"})      @MainThread      protected void onPostExecute(Result result) {      }        /**       * Runs on the UI thread after {@link #publishProgress} is invoked.       * The specified values are the values passed to {@link #publishProgress}.       *       * @param values The values indicating progress.       *       * @see #publishProgress       * @see #doInBackground       */      @SuppressWarnings({"UnusedDeclaration"})      @MainThread      protected void onProgressUpdate(Progress... values) {      }        /**       * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and       * {@link #doInBackground(Object[])} has finished.</p>       *        * <p>The default implementation simply invokes {@link #onCancelled()} and       * ignores the result. If you write your own implementation, do not call       * <code>super.onCancelled(result)</code>.</p>       *       * @param result The result, if any, computed in       *               {@link #doInBackground(Object[])}, can be null       *        * @see #cancel(boolean)       * @see #isCancelled()       */      @SuppressWarnings({"UnusedParameters"})      @MainThread      protected void onCancelled(Result result) {          onCancelled();      }            /**       * <p>Applications should preferably override {@link #onCancelled(Object)}.       * This method is invoked by the default implementation of       * {@link #onCancelled(Object)}.</p>       *        * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and       * {@link #doInBackground(Object[])} has finished.</p>       *       * @see #onCancelled(Object)        * @see #cancel(boolean)       * @see #isCancelled()       */      @MainThread      protected void onCancelled() {      }        /**       * Returns <tt>true</tt> if this task was cancelled before it completed       * normally. If you are calling {@link #cancel(boolean)} on the task,       * the value returned by this method should be checked periodically from       * {@link #doInBackground(Object[])} to end the task as soon as possible.       *       * @return <tt>true</tt> if task was cancelled before it completed       *       * @see #cancel(boolean)       */      public final boolean isCancelled() {          return mCancelled.get();      }        /**       * <p>Attempts to cancel execution of this task.  This attempt will       * fail if the task has already completed, already been cancelled,       * or could not be cancelled for some other reason. If successful,       * and this task has not started when <tt>cancel</tt> is called,       * this task should never run. If the task has already started,       * then the <tt>mayInterruptIfRunning</tt> parameter determines       * whether the thread executing this task should be interrupted in       * an attempt to stop the task.</p>       *        * <p>Calling this method will result in {@link #onCancelled(Object)} being       * invoked on the UI thread after {@link #doInBackground(Object[])}       * returns. Calling this method guarantees that {@link #onPostExecute(Object)}       * is never invoked. After invoking this method, you should check the       * value returned by {@link #isCancelled()} periodically from       * {@link #doInBackground(Object[])} to finish the task as early as       * possible.</p>       *       * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this       *        task should be interrupted; otherwise, in-progress tasks are allowed       *        to complete.       *       * @return <tt>false</tt> if the task could not be cancelled,       *         typically because it has already completed normally;       *         <tt>true</tt> otherwise       *       * @see #isCancelled()       * @see #onCancelled(Object)       */      public final boolean cancel(boolean mayInterruptIfRunning) {          mCancelled.set(true);          return mFuture.cancel(mayInterruptIfRunning);      }        /**       * Waits if necessary for the computation to complete, and then       * retrieves its result.       *       * @return The computed result.       *       * @throws CancellationException If the computation was cancelled.       * @throws ExecutionException If the computation threw an exception.       * @throws InterruptedException If the current thread was interrupted       *         while waiting.       */      public final Result get() throws InterruptedException, ExecutionException {          return mFuture.get();      }        /**       * Waits if necessary for at most the given time for the computation       * to complete, and then retrieves its result.       *       * @param timeout Time to wait before cancelling the operation.       * @param unit The time unit for the timeout.       *       * @return The computed result.       *       * @throws CancellationException If the computation was cancelled.       * @throws ExecutionException If the computation threw an exception.       * @throws InterruptedException If the current thread was interrupted       *         while waiting.       * @throws TimeoutException If the wait timed out.       */      public final Result get(long timeout, TimeUnit unit) throws InterruptedException,              ExecutionException, TimeoutException {          return mFuture.get(timeout, unit);      }        /**       * Executes the task with the specified parameters. The task returns       * itself (this) so that the caller can keep a reference to it.       *        * <p>Note: this function schedules the task on a queue for a single background       * thread or pool of threads depending on the platform version.  When first       * introduced, AsyncTasks were executed serially on a single background thread.       * Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed       * to a pool of threads allowing multiple tasks to operate in parallel. Starting       * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being       * executed on a single thread to avoid common application errors caused       * by parallel execution.  If you truly want parallel execution, you can use       * the {@link #executeOnExecutor} version of this method       * with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings       * on its use.       *       * <p>This method must be invoked on the UI thread.       *       * @param params The parameters of the task.       *       * @return This instance of AsyncTask.       *       * @throws IllegalStateException If {@link #getStatus()} returns either       *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.       *       * @see #executeOnExecutor(java.util.concurrent.Executor, Object[])       * @see #execute(Runnable)       */      @MainThread      public final AsyncTask<Params, Progress, Result> execute(Params... params) {          return executeOnExecutor(sDefaultExecutor, params);      }        /**       * Executes the task with the specified parameters. The task returns       * itself (this) so that the caller can keep a reference to it.       *        * <p>This method is typically used with {@link #THREAD_POOL_EXECUTOR} to       * allow multiple tasks to run in parallel on a pool of threads managed by       * AsyncTask, however you can also use your own {@link Executor} for custom       * behavior.       *        * <p><em>Warning:</em> Allowing multiple tasks to run in parallel from       * a thread pool is generally <em>not</em> what one wants, because the order       * of their operation is not defined.  For example, if these tasks are used       * to modify any state in common (such as writing a file due to a button click),       * there are no guarantees on the order of the modifications.       * Without careful work it is possible in rare cases for the newer version       * of the data to be over-written by an older one, leading to obscure data       * loss and stability issues.  Such changes are best       * executed in serial; to guarantee such work is serialized regardless of       * platform version you can use this function with {@link #SERIAL_EXECUTOR}.       *       * <p>This method must be invoked on the UI thread.       *       * @param exec The executor to use.  {@link #THREAD_POOL_EXECUTOR} is available as a       *              convenient process-wide thread pool for tasks that are loosely coupled.       * @param params The parameters of the task.       *       * @return This instance of AsyncTask.       *       * @throws IllegalStateException If {@link #getStatus()} returns either       *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.       *       * @see #execute(Object[])       */      @MainThread      public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,              Params... params) {          if (mStatus != Status.PENDING) {              switch (mStatus) {                  case RUNNING:                      throw new IllegalStateException("Cannot execute task:"                              + " the task is already running.");                  case FINISHED:                      throw new IllegalStateException("Cannot execute task:"                              + " the task has already been executed "                              + "(a task can be executed only once)");              }          }            mStatus = Status.RUNNING;            onPreExecute();            mWorker.mParams = params;          exec.execute(mFuture);            return this;      }        /**       * Convenience version of {@link #execute(Object...)} for use with       * a simple Runnable object. See {@link #execute(Object[])} for more       * information on the order of execution.       *       * @see #execute(Object[])       * @see #executeOnExecutor(java.util.concurrent.Executor, Object[])       */      @MainThread      public static void execute(Runnable runnable) {          sDefaultExecutor.execute(runnable);      }        /**       * This method can be invoked from {@link #doInBackground} to       * publish updates on the UI thread while the background computation is       * still running. Each call to this method will trigger the execution of       * {@link #onProgressUpdate} on the UI thread.       *       * {@link #onProgressUpdate} will not be called if the task has been       * canceled.       *       * @param values The progress values to update the UI with.       *       * @see #onProgressUpdate       * @see #doInBackground       */      @WorkerThread      protected final void publishProgress(Progress... values) {          if (!isCancelled()) {              getHandler().obtainMessage(MESSAGE_POST_PROGRESS,                      new AsyncTaskResult<Progress>(this, values)).sendToTarget();          }      }        private void finish(Result result) {          if (isCancelled()) {              onCancelled(result);          } else {              onPostExecute(result);          }          mStatus = Status.FINISHED;      }        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;              }          }      }        private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {          Params[] mParams;      }        @SuppressWarnings({"RawUseOfParameterizedType"})      private static class AsyncTaskResult<Data> {          final AsyncTask mTask;          final Data[] mData;            AsyncTaskResult(AsyncTask task, Data... data) {              mTask = task;              mData = data;          }      }  }</code></pre>    <p>从中我们知道了,线程池中线程的数量跟CPU内核多少有关,在一个处理队列中最多只有128个,这个并发数超过就会报异常,同时源码里也看到,是通过sHandler发送一个MESSAGE_POST_RESULT的消息进行最终处理的。</p>    <p>sHandler是一个静态的Handler对象,为了能够将执行环境切换到主线程,这就要求sHandler这个对象必须在主线程中创建。由于静态成员会在加载类的时候进行初始化,因此这就变相要求AsyncTask的类必须在主线程中加载,否则同一个进程中的AsyncTask都无法正常工作。</p>    <p>还有一点要注意下,从Android 3.0开始,默认情况下AsyncTask是串行执行的。但在Android 3.0之前是并行执行的。</p>    <p>HandlerThread</p>    <p>HandlerThread继承了Thread,它是一种可以使用Handler的Thread,它的实现很简单,就在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环,这样在实际的使用中就允许在HandlerThread中创建Handler。看下源代码:</p>    <pre>  <code class="language-java">public class HandlerThread extends Thread {      int mPriority;      int mTid = -1;      Looper mLooper;        public HandlerThread(String name) {          super(name);          mPriority = Process.THREAD_PRIORITY_DEFAULT;      }        /**       * Constructs a HandlerThread.       * @param name       * @param priority The priority to run the thread at. The value supplied must be from        * {@link android.os.Process} and not from java.lang.Thread.       */      public HandlerThread(String name, int priority) {          super(name);          mPriority = priority;      }        /**       * Call back method that can be explicitly overridden if needed to execute some       * setup before Looper loops.       */      protected void onLooperPrepared() {      }        @Override      public void run() {          mTid = Process.myTid();          Looper.prepare();          synchronized (this) {              mLooper = Looper.myLooper();              notifyAll();          }          Process.setThreadPriority(mPriority);          onLooperPrepared();          Looper.loop();          mTid = -1;      }        /**       * This method returns the Looper associated with this thread. If this thread not been started       * or for any reason is isAlive() returns false, this method will return null. If this thread        * has been started, this method will block until the looper has been initialized.         * @return The looper.       */      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;      }        /**       * Quits the handler thread's looper.       * <p>       * Causes the handler thread's looper to terminate without processing any       * more messages in the message queue.       * </p><p>       * Any attempt to post messages to the queue after the looper is asked to quit will fail.       * For example, the {@link Handler#sendMessage(Message)} method will return false.       * </p><p class="note">       * Using this method may be unsafe because some messages may not be delivered       * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure       * that all pending work is completed in an orderly manner.       * </p>       *       * @return True if the looper looper has been asked to quit or false if the       * thread had not yet started running.       *       * @see #quitSafely       */      public boolean quit() {          Looper looper = getLooper();          if (looper != null) {              looper.quit();              return true;          }          return false;      }        /**       * Quits the handler thread's looper safely.       * <p>       * Causes the handler thread's looper to terminate as soon as all remaining messages       * in the message queue that are already due to be delivered have been handled.       * Pending delayed messages with due times in the future will not be delivered.       * </p><p>       * Any attempt to post messages to the queue after the looper is asked to quit will fail.       * For example, the {@link Handler#sendMessage(Message)} method will return false.       * </p><p>       * If the thread has not been started or has finished (that is if       * {@link #getLooper} returns null), then false is returned.       * Otherwise the looper is asked to quit and true is returned.       * </p>       *       * @return True if the looper looper has been asked to quit or false if the       * thread had not yet started running.       */      public boolean quitSafely() {          Looper looper = getLooper();          if (looper != null) {              looper.quitSafely();              return true;          }          return false;      }        /**       * Returns the identifier of this thread. See Process.myTid().       */      public int getThreadId() {          return mTid;      }  }</code></pre>    <p>IntentService</p>    <p>IntentService是一种特殊的Service,它继承了Service并且它是一种抽象类,因此必须创建它的子类才能使用IntentService。IntentService可用于执行后台耗时的任务,当任务执行后它会自动停止,同时由于IntentService是服务的原因,这导致他的优先级比单纯的线程要高很多,所以IntentService比较适合执行一些高优先级的后台任务,因为它的优先级高不容易被系统杀死。看下源码:</p>    <pre>  <code class="language-java">public abstract class IntentService extends Service {      private volatile Looper mServiceLooper;      private volatile ServiceHandler mServiceHandler;      private String mName;      private boolean mRedelivery;        private final class ServiceHandler extends Handler {          public ServiceHandler(Looper looper) {              super(looper);          }            @Override          public void handleMessage(Message msg) {              onHandleIntent((Intent)msg.obj);              stopSelf(msg.arg1);          }      }        /**       * Creates an IntentService.  Invoked by your subclass's constructor.       *       * @param name Used to name the worker thread, important only for debugging.       */      public IntentService(String name) {          super();          mName = name;      }        /**       * Sets intent redelivery preferences.  Usually called from the constructor       * with your preferred semantics.       *       * <p>If enabled is true,       * {@link #onStartCommand(Intent, int, int)} will return       * {@link Service#START_REDELIVER_INTENT}, so if this process dies before       * {@link #onHandleIntent(Intent)} returns, the process will be restarted       * and the intent redelivered.  If multiple Intents have been sent, only       * the most recent one is guaranteed to be redelivered.       *       * <p>If enabled is false (the default),       * {@link #onStartCommand(Intent, int, int)} will return       * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent       * dies along with it.       */      public void setIntentRedelivery(boolean enabled) {          mRedelivery = enabled;      }        @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);      }        @Override      public void onStart(@Nullable Intent intent, int startId) {          Message msg = mServiceHandler.obtainMessage();          msg.arg1 = startId;          msg.obj = intent;          mServiceHandler.sendMessage(msg);      }        /**       * You should not override this method for your IntentService. Instead,       * override {@link #onHandleIntent}, which the system calls when the IntentService       * receives a start request.       * @see android.app.Service#onStartCommand       */      @Override      public int onStartCommand(@Nullable Intent intent, int flags, int startId) {          onStart(intent, startId);          return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;      }        @Override      public void onDestroy() {          mServiceLooper.quit();      }        /**       * Unless you provide binding for your service, you don't need to implement this       * method, because the default implementation returns null.       * @see android.app.Service#onBind       */      @Override      @Nullable      public IBinder onBind(Intent intent) {          return null;      }        /**       * This method is invoked on the worker thread with a request to process.       * Only one Intent is processed at a time, but the processing happens on a       * worker thread that runs independently from other application logic.       * So, if this code takes a long time, it will hold up other requests to       * the same IntentService, but it will not hold up anything else.       * When all requests have been handled, the IntentService stops itself,       * so you should not call {@link #stopSelf}.       *       * @param intent The value passed to {@link       *               android.content.Context#startService(Intent)}.       *               This may be null if the service is being restarted after       *               its process has gone away; see       *               {@link android.app.Service#onStartCommand}       *               for details.       */      @WorkerThread      protected abstract void onHandleIntent(@Nullable Intent intent);  }</code></pre>    <h3>Android中的线程池</h3>    <p>线程池的优点:</p>    <ul>     <li>重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。</li>     <li>能有效控制线程池中的最大并发数,避免大量的线程之间因为互相抢占系统资源而导致的阻塞现象。</li>     <li>能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。</li>    </ul>    <p>Android中的线程池的概念来源于Java中的Executor,Executor是一个接口,真正的线程池的实现为ThreadPoolExecutor。ThreadPoolExecutor提供一系列参数来配置线程池,通过不同的参数可以创建不同的线程池,从线程池的功能特性来说,线程池主要分为4类。</p>    <p>ThreadPoolExecutor执行任务时大致遵循以下规则:</p>    <ol>     <li>如果线程池中的线程数量未达到核心线程的数量,那么会直接启动一个核心线程来执行任务。</li>     <li>如果线程中的线程数量已经达到或者超过核心线程的数量,那么任务会被插入到任务队列中排队等待执行。</li>     <li>如果在步骤2中无法将任务插入到任务队列中,这往往是由于任务队列已经满了, 这个时候如果线程数量未达到线程池规定的最大值,那么会立刻启动一个非核心线程来执行任务。</li>     <li>如果步骤3的中线程数量已经达到线程池规定的最大值,那么就拒绝执行此任务,ThreadPoolExecutor会调用RejectedExecutionHandler的rejectedExecution方法来通知调用者。</li>    </ol>    <p>线程池主要有4类:</p>    <ul>     <li>FixThreadPool:这是一种线程数量固定的线程池,当线程处于空闲的时候,并不会被回收,除非线程池被关闭了。</li>     <li>CachedThreadPool:这是一种线程数量不定的线程池,它只有非核心线程,并且最大线程数为Integer.MAX_VALUE。</li>     <li>ScheduledThreadPool:它的核心线程数量是固定的,而非核心线程数是没有限制的,并且当非核心线程闲置时会被立即回收。</li>     <li>SingleThreadExecutor:这类线程池内部只有一个核心线程,它确保所有的任务都在同一个线程中按顺序执行。</li>    </ul>    <p> </p>    <p>来自:http://www.jianshu.com/p/24e6bf173082</p>    <p> </p>