Android中的那些線程--AsyncTask, HandlerThread,IntentService

今天要分享的是Android基礎(chǔ)知識(shí)篇,往往我們都是拿來主義,知道怎么用卻不知道原理,今天就來講講Android線程相關(guān)的知識(shí)點(diǎn)吧。一如既往的,寫文初心,便于追溯,總結(jié)知識(shí),如果能給看到這篇文章的你提供幫助,那價(jià)值就更大了。

Android中線程分為主線程和子線程,主線程主要用于UI相關(guān)的事務(wù),是進(jìn)程默認(rèn)情況下?lián)碛械木€程,looper是main looper,在主線程中不能做耗時(shí)操作,因?yàn)橹骶€程對(duì)于響應(yīng)速度要求很高,如果五秒不響應(yīng)系統(tǒng)就會(huì)出現(xiàn)ANR報(bào)錯(cuò),就算不超過五秒耗時(shí)操作也會(huì)造成界面的卡頓,嚴(yán)重影響用戶體驗(yàn),所以一定要記住耗時(shí)操作不要在主線程中進(jìn)行,比如數(shù)據(jù)庫訪問,網(wǎng)絡(luò)訪問等,當(dāng)然在Android3.0以上如果在主線程中進(jìn)行網(wǎng)絡(luò)訪問就會(huì)報(bào)NetworkOnMainThreadExcepetion異常。而子線程可以說是工作線程的,可用于耗時(shí)操作,網(wǎng)絡(luò)請求等。

子線程我們最熟悉的實(shí)現(xiàn)方式就是Thread,但是Thread的大量new可不是一件好事情,在阿里巴巴編程規(guī)范里面就有提到建議不要直接new Thread 應(yīng)該用線程池來代替,可以管理和復(fù)用線程。在Android中除了Thread的呢,還有HandlerThread,AsyncTask以及IntentService,當(dāng)然啦,還有線程池。AsyncTask相信很多人都有用到過,用于在主線程創(chuàng)建并且進(jìn)行異步操作,在回調(diào)方法中可進(jìn)行UI的刷新和操作進(jìn)程的監(jiān)聽等。 而IntentService呢,內(nèi)部其實(shí)也是Thread和Handler實(shí)現(xiàn)的,它的優(yōu)勢在于它是一個(gè)service可以在后臺(tái)運(yùn)行,相對(duì)來說優(yōu)先級(jí)比其他線程來說更好,不容易被系統(tǒng)殺死。
HandlerThread是具有消息循環(huán)的線程,我們可以利用HnandlerThread在其中運(yùn)行Handler從而將一個(gè)Handler建立在子線程中運(yùn)行。而AsyncTask則是內(nèi)部封裝了線程池和Handler,接下來我們會(huì)分別分析AsyncTask的源碼看看它是如何完成整個(gè)過程的,以及IntentService,HandlerThread相關(guān)原理和使用。

AsyncTask

AsyncTask 用于異步任務(wù)執(zhí)行,利用線程池在后臺(tái)執(zhí)行任務(wù),然后借助于Handler將任務(wù)進(jìn)程以及任務(wù)結(jié)果返回到UI,從而實(shí)現(xiàn)在子線程中進(jìn)行耗時(shí)操作,而在主線程更新UI的功能,對(duì)于我們程序中請求網(wǎng)絡(luò)并且刷新UI來說是個(gè)很好的選擇,但是呢,從下面這段從源碼摘抄過來的類注釋可以看出,AsyncTask不適用于特別耗時(shí)的后臺(tái)任務(wù),只適用于幾秒的操作,對(duì)于特別耗時(shí)的后臺(tái)任務(wù)建議使用線程池或者FutureTask。

syncTask is designed to be a helper class around {@link Thread} and {@link Handler}
* and does not constitute a generic threading framework. AsyncTasks should ideally be
* used for short operations (a few seconds at the most.) If you need to keep threads
* running for long periods of time, it is highly recommended you use the various APIs
* provided by the <code>java.util.concurrent</code> package such as {@link Executor},
* {@link ThreadPoolExecutor} and {@link FutureTask}.</p>

疑問: 為什么AsyncTask不適用于特別長時(shí)間的耗時(shí)操作呢?

  1. AsyncTask的生命周期和Activity不一致,如果是操作時(shí)間太長的話,當(dāng)Activity由于旋轉(zhuǎn)屏幕或者其他原因銷毀了的時(shí)候,當(dāng)操作執(zhí)行完會(huì)找不到要更新的UI從而報(bào)錯(cuò)。java.lang.IllegalArgumentException: View not attached to window manager. 比如你想關(guān)于一個(gè)dialog,你并沒有在onstop中去dimiss掉這個(gè)dialog。
  2. 因?yàn)锳syncTask在執(zhí)行長時(shí)間的耗時(shí)任務(wù)時(shí)也會(huì)持有一個(gè)Activity對(duì)象,即使這個(gè)Activity已經(jīng)不可見了,Android也無法對(duì)這個(gè)Activity進(jìn)行回收,導(dǎo)致內(nèi)存泄露。
  3. 當(dāng)然你可能會(huì)問,難道AsyncTask不能手動(dòng)cancel,答案當(dāng)然是可以啦, 但是AsyncTask的cancel方法有一個(gè)弊端,那就是當(dāng)doInBackground()正在執(zhí)行一個(gè)不可打斷的工作的方法會(huì)失效,比如BitmapFactory.decodeStream()的IO操作,當(dāng)然只要你想cancel成功,你也可以在cancel之前強(qiáng)制停止IO操作,捕捉異常,保證AsyncTask準(zhǔn)確的被cancel,關(guān)于AsyncTask的Cancel的使用等會(huì)會(huì)簡單介紹一下,是有一點(diǎn)小差別的。

下面我們一起來看看AsyncTask的源碼然后看看實(shí)現(xiàn)原理.

public abstract class AsyncTask<Params, Progress, Result> {

首先AsyncTask是一個(gè)抽象類,它有三個(gè)泛型參數(shù),從字面意思可知,第一個(gè)是參數(shù),第二個(gè)是任務(wù)進(jìn)度,第三個(gè)是返回結(jié)果類型。
要使用AsyncTask的時(shí)候必須繼承實(shí)現(xiàn)抽象方法。AsyncTask有4個(gè)核心的方法。 如下:

注: 此段源碼摘抄自android-26
從注解可知: onPreExecute是工作在主線程中的一個(gè)方法,主要用于在開始執(zhí)行異步任務(wù)之前做一些前期準(zhǔn)備工作。
 @MainThread
    protected void onPreExecute() {
    }
    
    doInBackground是在工作線程即子線程執(zhí)行后臺(tái)任務(wù)的方法,在這里你可以實(shí)現(xiàn)你要執(zhí)行的后臺(tái)任務(wù),數(shù)據(jù)庫請求網(wǎng)絡(luò)請求等。 參數(shù)Params和創(chuàng)建AsyncTask子類的時(shí)候Params同類型的參數(shù),用于給后臺(tái)任務(wù)提供一些信息。在這個(gè)方法,可以通過調(diào)用publicProgress來更新任務(wù)進(jìn)度,publicProgress會(huì)調(diào)用onProgressUpdate方法。
    并且在這個(gè)方法將返回任務(wù)執(zhí)行的返回結(jié)果,結(jié)果會(huì)被onPostExecute接收并處理
    @WorkerThread
protected abstract Result doInBackground(Params... params);

  
    這個(gè)方法執(zhí)行在主線程中用于監(jiān)聽當(dāng)前任務(wù)的進(jìn)度,可以根據(jù)進(jìn)度更新主線程UI告知用戶任務(wù)執(zhí)行的進(jìn)度的。
    @MainThread
    protected void onProgressUpdate(Progress... values) {
    }
    
    同樣此方法運(yùn)行在主線程中,用于接收任務(wù)的結(jié)果,
    @MainThread
    protected void onPostExecute(Result result) {
    }

這四個(gè)方法的執(zhí)行順序是: 1.onPreExecute 2. doInBackground 最后是onPostExecute。在doInBackground中如果有調(diào)用publicProgress方法被調(diào)用的話就會(huì)執(zhí)行onProgressUpdate方法。

AsyncTask還提供了cancel方法如下:

當(dāng)mayInterruptIfRunning is true 則中斷當(dāng)前正在執(zhí)行的任務(wù),false則允許當(dāng)前正在執(zhí)行的任務(wù)執(zhí)行完才結(jié)束。調(diào)用此方法之后會(huì)回調(diào)onCanceled()方法,不會(huì)調(diào)用onPostExecute方法、
 public final boolean cancel(boolean mayInterruptIfRunning) {
        mCancelled.set(true);
        return mFuture.cancel(mayInterruptIfRunning);
    }

,但是要注意的是,AsyncTask中的cancel()方法并不是真正去取消任務(wù),只是設(shè)置這個(gè)任務(wù)為取消狀態(tài),我們需要在doInBackground()判斷終止任務(wù)。

下面是一個(gè)簡單的應(yīng)用實(shí)例:

  /**
     *  URL  下載地址
     *  Integer 下載進(jìn)度
     *  Integer 下載結(jié)果 總共下載的文件長度
     */
    public static class DownLoadingFileAsyncTask  extends AsyncTask<URL, Integer, Integer>{
        private static final String TAG = DownLoadingFileAsyncTask.class.getSimpleName();
        @Override
        protected void onPreExecute() {
            Log.i(TAG, "onPostExecute");
        }

        @Override
        protected void onPostExecute(Integer integer) {
            Log.i(TAG, "onPostExecute");
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            Log.i(TAG, "onProgressUpdate"  +  values[0]);
        }

        @Override
        protected Integer doInBackground(URL... urls) {
            int length = 0;
            for (URL url : urls) {
                length = downloadFile(url);
                publishProgress(length);
                if (isCancelled()){
                    break;
                }
            }
            return length;
        }

    }

使用方法:
new DownLoadingFileAsyncTask().execute(url1, url2, url3);

這里我只是示意一下所以實(shí)現(xiàn)都比較簡單,我執(zhí)行了一個(gè)下載文件的操作,并且調(diào)用publicProgress方法更新下載進(jìn)度,在onProgressUpdate里面打印了當(dāng)前下載的進(jìn)度.

從我們調(diào)用的方法的入口我們來看看AsyncTask是如何實(shí)現(xiàn)的:

首先看看execute方法:

    @MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

從注解可以知道首先execute必須在主線程執(zhí)行,可以看到這個(gè)方法只是調(diào)用了executeOnExecutor方法。 sDefaultExecutor是一個(gè)串行的線程池d.定義如下:

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
  
  public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
 private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
            //向隊(duì)列尾部插入一個(gè)新的runable對(duì)象
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }
        
       //取出隊(duì)列頭部第一個(gè)任務(wù)并且不為null的執(zhí)行
        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
               //用于執(zhí)行任務(wù)的線程池 THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }

從上面可以知道sDefaultExecutor是一個(gè)靜態(tài)的SerialExecutor對(duì)象,從SerialExecutor的實(shí)現(xiàn)可以看出它是一個(gè)一個(gè)執(zhí)行任務(wù)的,當(dāng)前沒有active的任務(wù)的時(shí)候,就會(huì)調(diào)用scheduleNext()執(zhí)行下一個(gè)任務(wù)。并且是串行執(zhí)行。

需要注意的是:這個(gè)方法是執(zhí)行的時(shí)候AsyncTask是串行執(zhí)行還是并行執(zhí)行取決于Android版本,在一開始的Android1.6之前AsyncTask是串行執(zhí)行的,但Android1.6之后AsyncTask變成了并行執(zhí)行,不過為了避免的并行帶來的麻煩,Android3.0又開始使用單線程串行執(zhí)行,這個(gè)在源碼中的方法的注解中都有明確的說明的,不過不是說Android3.0方法以后就不能執(zhí)行并行操作了,你可以用這個(gè)方法實(shí)現(xiàn)AsyncTask的的并行操作。executeOnExecutor 如下:

 new DownLoadingFileAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url1, url2, url3);
new DownLoadingFileAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url1, url2, url3);
new DownLoadingFileAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url1, url2, url3);
new DownLoadingFileAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url1, url2, url3);
        

一起來看看executeOnExecutor的實(shí)現(xiàn):

  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;
        
        //調(diào)用了onPreExecute()方法s
        onPreExecute();

        mWorker.mParams = params;
        exec.execute(mFuture);

executeOnExecutor首先判斷一下當(dāng)前AsyncTask的狀態(tài)是否正在運(yùn)行或者已經(jīng)執(zhí)行完了,然后是就拋出異常,所以這也決定了AsyncTask的execute必須也只能調(diào)用一次 . 可以看到在這個(gè)方法中首先調(diào)用了onPreExecute方法。 然后執(zhí)行線程池執(zhí)行了mFuture這個(gè)RunableTask,而mFuture呢就是執(zhí)行的mWorker這個(gè)Runable的call方法。

mWorker和mFuture的定義如下:

    private final WorkerRunnable<Params, Result> mWorker;
    private final FutureTask<Result> mFuture;
    
   private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
       Params[] mParams;
    }

  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
                    //調(diào)用了doInBackground方法
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
                   //發(fā)送result到Handler
                    postResult(result);
                }
                return result;
            }
        };

    mFuture = new FutureTaskd<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);
            }
        }
    }; 

executeOnExecutor方法中將params賦值給了mWorker的params對(duì)象,mWorker的call方法中執(zhí)行了doInBackground并且將結(jié)果通過Hanlder發(fā)送出去。

Handler如下:

 private static class InternalHandler extends Handler {
        public InternalHandler(Looper looper) {
            super(looper);
        }

        @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;
            }
        }
    }

InternalHandler接收到MESSAGE_POST_RESULT之后調(diào)用了AsyncTask的finish方法如下:

  private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

可以看到finish方法首先判斷了是否被取消,如果取消了就調(diào)用onCanceled方法把結(jié)果返回,否則回調(diào)onPostExecute,將結(jié)果返回,至此我們將 一個(gè)任務(wù)的執(zhí)行到返回結(jié)果的路徑都跟蹤完了。這就是任務(wù)異步執(zhí)行的全過程, InternalHandler是一個(gè)運(yùn)行在主線程中的Handler,new的語句如下:

     private static Handler getMainHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler(Looper.getMainLooper());
            }
            return sHandler;
        }
    }

下面我們一起看看更新進(jìn)度的方法publishProgress:

    @WorkerThread
    protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();
        }
    }

顯而易見,該方法向handler發(fā)送了MESSAGE_POST_PROGRESS消息,Handler回調(diào)了onProgressUpdate(result.mData)方法。

現(xiàn)在終于清楚了整個(gè)調(diào)用的過程了吧。 其實(shí)AsyncTask的源碼注釋說明里面也給出了很清楚的解說,所以多看看源碼也有利于我們更加了解類的實(shí)現(xiàn)和原理。
這里需要注意的是: 在Android5.0以下AsyncTask必須在主線程中加載,至于為什么很簡單,因?yàn)镮nternalHandler是一個(gè)靜態(tài)內(nèi)部類,而它又必須有主線程的looper,靜態(tài)內(nèi)部類在類加載的時(shí)候就完成初始化,所以這就要求AsyncTask必須在主線程中執(zhí)行。

HandlerThread

我們直接看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;
    }

} 
此處只貼出關(guān)鍵的部分,感興趣的可以自己去看完整的源碼哦,我就不全貼出來湊字?jǐn)?shù)了。^_^
    

HandlerThread繼承自Thread,在run里面利用Looper實(shí)現(xiàn)了消息隊(duì)列功能,我們都知道Handler的原理中就包含了Looper,Looper負(fù)責(zé)消息的循環(huán),這里也是一樣的,HandlerThread借助Looper無線循環(huán)的輪詢,從而執(zhí)行對(duì)應(yīng)的Message。同時(shí)HandlerThread提供了quit和quitSafely方法,因?yàn)閘ooper是無線循環(huán)的,所以不需要時(shí),記得養(yǎng)成良好的習(xí)慣停止HandlerThread,應(yīng)用場景如下:

一般我們在程序中借助handlerThread來開啟一個(gè)非主線程的Handler進(jìn)行消息處理做一些耗時(shí)的操作。
HandlerThread handlerThread  = new HandlerThread("worker thread");
        handlerThread.start();
        Handler handler = new Handler(handlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            }
        };

HandlerThread相對(duì)簡單一點(diǎn),所以我們就將這么多了。

IntentService

顧名思義,IntentService是一個(gè)繼承與service的類,內(nèi)部利用HandlerThread和handler實(shí)現(xiàn)了對(duì)消息的傳遞。IntentService是一個(gè)抽象類,子類必須繼承onHandlerIntent方法用于對(duì)消息的處理。

/**
    * 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);

從注釋可以看到這個(gè)方法也是串行的,所以當(dāng)有很多請求的時(shí)候回堵塞當(dāng)前IntentService的其他請求,當(dāng)所有請求都被執(zhí)行完了之后,IntentService會(huì)調(diào)用stopSelf停止他自己。
IntentSerivce是如何對(duì)外界Intent進(jìn)行處理的, 每次調(diào)用Service的時(shí)候雖然只會(huì)調(diào)用一次onCreate,但是會(huì)重復(fù)調(diào)用onStartCommond方法,onStartCommond里面調(diào)用了onStart方法,看看onStart做了什么。

    @Override
   public void onStart(@Nullable Intent intent, int startId) {
       Message msg = mServiceHandler.obtainMessage();
       msg.arg1 = startId;
       msg.obj = intent;
       mServiceHandler.sendMessage(msg);
   }

onStart將startId以及Intent包裹在msg里面發(fā)送到了ServiceHandler,在看看ServiceHandler做了些什么。

   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);
       }
   }

不管接收到了什么消息,ServiceHandler都是直接回調(diào)onHandlerIntent方法。然后停止自己。而上面我們說了onHandlerIntent的方法是有子類實(shí)現(xiàn)的,所以子類自己實(shí)現(xiàn)然后處理相應(yīng)的Intent消息。

最后一下有關(guān)于線程池的知識(shí):

線程池的優(yōu)點(diǎn): 實(shí)現(xiàn)線程的復(fù)用,控制線程池最大的并發(fā)數(shù),對(duì)線程進(jìn)行管理。
這里我只提及一下ThreadPoolExecutor的構(gòu)造方法。

通過配置相關(guān)的參數(shù)創(chuàng)建一個(gè)線程池。
參數(shù)解說如下:
1.corePoolSize  線程池中核心線程數(shù)
2、maximumPoolSize 線程池中允許的最大線程數(shù)
3.keepAliveTime 非核心線程閑置時(shí)的超時(shí)時(shí)間,超過就會(huì)被回收掉,如果allowCoreThreadTimeOut為true,核心線程也會(huì)被回收掉。
4.unit 超時(shí)的時(shí)間單位
5. 線程池中的任務(wù)隊(duì)列
6.創(chuàng)建線程工廠
   public ThreadPoolExecutor(int corePoolSize,
                             int maximumPoolSize,
                             long keepAliveTime,
                             TimeUnit unit,
                             BlockingQueue<Runnable> workQueue,
                             ThreadFactory threadFactory) {
       this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
            threadFactory, defaultHandler);
   }

核心線程會(huì)一直在線程池中不會(huì)被回收,除非allowCoreThreadTimeOut 為true。那么當(dāng)核心線程閑置時(shí)間超過keepAliveTime的時(shí)候就會(huì)回收掉。

非核心線程當(dāng)閑置的時(shí)候就會(huì)被回收掉。當(dāng)活動(dòng)線程達(dá)到最大線程池的時(shí)候,后面的線程就會(huì)被阻塞。

ThreadPoolExecutor執(zhí)行任務(wù)的規(guī)則:

  1. 如果線程池中的線程數(shù)量未達(dá)到核心線程的數(shù)量,那么會(huì)直接啟動(dòng)一個(gè)核心線程來執(zhí)行任務(wù)
  2. 如果線程池中的線程數(shù)量已經(jīng)超過了核心線程數(shù)量則插入任務(wù)隊(duì)列里面等待
  3. 當(dāng)任務(wù)隊(duì)列滿了的時(shí)候,并且線程沒有達(dá)到規(guī)定的最大線程的數(shù)量的時(shí)候則啟動(dòng)一個(gè)非核心線程執(zhí)行任務(wù)。
  4. 如果線程數(shù)量已經(jīng)超過了最大線程池?cái)?shù)量,則拒絕任務(wù)調(diào)用RejectedExecutionHandler的rejectedExecution來通知調(diào)用者。

我們常見的線程池子類有: FixedThreadPool, CachedThreadPool,ScheduledThreadPool,SingleThreadExecutor。這些只是配置了不同參數(shù)的線程池而已,所以感興趣的可以自己百度看看哦。

好了 碼了這么久,終于學(xué)習(xí)筆記總結(jié)完了,總結(jié)了一下之后,感覺把之前看的知識(shí)點(diǎn)又重新溫習(xí)了一遍,影響更加深刻了,受益匪淺。 不知道 看到這里,你學(xué)會(huì)了多少。有總結(jié)的不對(duì)的地方,請不吝指出,歡迎討論, 謝謝。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容