Androidスレッドプールはこう使います

8842 ワード

背景
前にスレッドとマルチスレッドについて2つの文章を書いて、意外にもマルチスレッドを書いて、それはスレッドプールが欠かせないに違いありません.もしスレッドとスレッドプールの知識を知りたいなら、私が前に書いたスレッドを見てもいいです.あなたは本当にそれを知っていますか.これが本当のマルチスレッドです.では、スレッドプールとは何ですか.どんなメリットがありますか.1.スレッドプール内のスレッドを再利用し、スレッドの作成と破棄によるパフォーマンスオーバーヘッドを回避します.スレッドプールの最大同時数を効果的に制御し、大量のスレッド間でシステムリソースを奪い合うことによるスレッドの詰まりを回避できます.2.スレッドを簡単に管理でき、タイミング実行や指定間隔ループ実行などの機能を提供できる.3.AsyncTaskに比べて、最大の利点は、スレッドが制御可能であることです.たとえば、ページを離れると、AsyncTaskにコミットできないタスクは取り消すことができず、スレッドプールは不要なときにスレッドを削除することができます.
スレッドプールとは
では、スレッドプールはどのように作成すればいいのでしょうか.まず、スレッドプールの作成方法を見てみましょう.
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

まず各パラメータの意味を見てみましょう.1.corePoolSize:コアプールのサイズは、スレッドプールを作成した後、デフォルトでは、スレッドプールにはスレッドがありません.タスクが来るのを待ってスレッドを作成してタスクを実行します.スレッドプールのスレッド数がcorePoolSizeに達すると、到着したタスクをキャッシュキューに入れます.この数を超えるスレッドは、ワークキューがいっぱいになった場合にのみ作成されます.スレッドの空き時間がアクティブ時間を超えている場合は、回収可能としてマークされ、スレッドプールの現在のサイズがcorePoolSizeを超えている場合にのみスレッドが終了します.ユーザはprestartAllCoreThreads()またはprestartCoreThread()メソッドを呼び出してスレッドを事前に作成することができます.すなわち、タスクが来ない前にcorePoolSizeスレッドまたはスレッドを作成します.
  • maximumPoolSize:スレッドプールの最大スレッド数、このパラメータも非常に重要なパラメータであり、オンライン・プログラム・プールで最大何個のスレッドを作成できるかを示します.この値より大きい場合、Threadは廃棄処理機構によって処理される.
  • keepAliveTime:スレッドがタスク実行されていない場合、最大どのくらいの時間で終了するかを示します.デフォルトでは、スレッドプール内のスレッド数がcorePoolSizeより大きい場合にのみ、keepAliveTimeは、スレッドプール内のスレッド数がcorePoolSizeより大きくないまで機能します.すなわち、スレッドプール内のスレッド数がcorePoolSizeより大きい場合、1つのスレッドの空き時間がkeepAliveTimeに達すると、スレッドプール内のスレッド数がcorePoolSizeを超えないまで終了します.しかしallowCoreThreadTimeOut(boolean)メソッドが呼び出されると、オンライン・スレッド・プールのスレッド数がcorePoolSizeより大きくない場合、keepAliveTimeパラメータもスレッド・プールのスレッド数が0になるまで機能します.
  • Unit:パラメータkeepAliveTimeの時間単位で、7種類の値が取り、TimeUnitクラスには7種類の静的属性があります.
  • workQueue:実行待ちのタスクを格納するブロックキューで、スレッドプール内のスレッド数がcorePoolSizeに達すると、到着したタスクをキャッシュキューに格納します.
  • threadFactory:スレッドファクトリ、主にスレッドの作成に使用されます.
  • handler:タスクの処理を拒否した場合のポリシー、すなわちパラメータmaximumPoolSizeが到達した後に処理を破棄する方法を示す.次の4つの値があります.AbortPolicy:タスクを破棄し、RejectedExecutionException例外を放出します.ThreadPoolExecutor.DiscardPolicy:タスクも破棄されますが、例外は放出されません.ThreadPoolExecutor.DiscardOldestPolicy:キューの一番前のタスクを破棄し、タスクの実行を再試行します(この手順を繰り返します).CallerRunsPolicy:このタスクを呼び出しスレッドで処理するユーザーは、インタフェースRejectedExecutionHandlerが独自のポリシーをカスタマイズすることもできます.

  • スレッドプールDemo
    これはネット上で探している簡単なスレッドプールの実装コードです.
    動的エージェントを使用してThreadPoolProxyFactoryを作成します.スレッドプールを取得するには、通常のスレッドプールとダウンロードしたスレッドプールの2つの方法があります.
    public class ThreadPoolProxyFactory {
        static ThreadPoolProxy mNormalThreadPoolProxy;
        static ThreadPoolProxy mDownLoadThreadPoolProxy;
    
        /**
         *            mNormalThreadPoolProxy
         */
        public static ThreadPoolProxy getNormalThreadPoolProxy() {
            if (mNormalThreadPoolProxy == null) {
                synchronized (ThreadPoolProxyFactory.class) {
                    if (mNormalThreadPoolProxy == null) {
                        mNormalThreadPoolProxy = new ThreadPoolProxy(5, 5);
                    }
                }
            }
            return mNormalThreadPoolProxy;
        }
    
        /**
         *            mDownLoadThreadPoolProxy
         */
        public static ThreadPoolProxy getDownLoadThreadPoolProxy() {
            if (mDownLoadThreadPoolProxy == null) {
                synchronized (ThreadPoolProxyFactory.class) {
                    if (mDownLoadThreadPoolProxy == null) {
                        mDownLoadThreadPoolProxy = new ThreadPoolProxy(3, 3);
                    }
                }
            }
            return mDownLoadThreadPoolProxy;
        }
    }

    スレッドプールエージェントは、スレッドプールの代わりにいくつかの操作を完了します.タスクの実行、タスクのコミット、タスクの削除の3つの方法があります.
    public class ThreadPoolProxy {
    
        ThreadPoolExecutor mExecutor;
        private int mCorePoolSize;
        private int mMaximumPoolSize;
    
    
        /**
         * @param corePoolSize          
         * @param maximumPoolSize      
         */
        public ThreadPoolProxy(int corePoolSize, int maximumPoolSize) {
            mCorePoolSize = corePoolSize;
            mMaximumPoolSize = maximumPoolSize;
        }
    
        /**
         *    ThreadPoolExecutor
         *       ,                   ,     
         */
        private void initThreadPoolExecutor() {
            if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
                synchronized (ThreadPoolProxy.class) {
                    if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
                        long keepAliveTime = 3000;
                        TimeUnit unit = TimeUnit.MILLISECONDS;
                        BlockingQueue workQueue = new LinkedBlockingDeque<>();
                        ThreadFactory threadFactory = Executors.defaultThreadFactory();
                        RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
    
                        mExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, keepAliveTime, unit, workQueue,
                                threadFactory, handler);
                    }
                }
            }
        }
        /**
                     ?
         1.     
            execute->     
            submit-->    
         2.Future     ?
            1.                    ,    get  ,get         
            2.get          ===>                  
         */
        /**
         *     
         */
        public void execute(Runnable task) {
            initThreadPoolExecutor();
            mExecutor.execute(task);
        }
    
        /**
         *     
         */
        public Future submit(Runnable task) {
            initThreadPoolExecutor();
            return mExecutor.submit(task);
        }
    
        /**
         *     
         */
        public void remove(Runnable task) {
            initThreadPoolExecutor();
            mExecutor.remove(task);
        }
    }

    では、スレッドプールをどのように使用しますか.
    ThreadPoolProxyFactory .getNormalThreadPoolProxy().execute(Runnable);
    

    まとめ
    これは多分Androidスレッドプールの使用ですが、何か悪いところがあったらメッセージを歓迎します.私たちは一緒に交流して、みんなを書きます.優先度スレッドプールの実装に興味のある友人も、優先度スレッドプールの実装を学ぶことができます.