zoukankan      html  css  js  c++  java
  • Android线程和线程池

    Translated From Google Android.

    class PhotoDecodeRunnable implements Runnable {
    ...
        /*
         * Defines the code to run for this task.
         */
        @Override
        public void run() {
            // Moves the current Thread into the background
            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
            ...
            /*
             * Stores the current Thread in the the PhotoTask instance,
             * so that the instance
             * can interrupt the Thread.
             */
            mPhotoTask.setImageDecodeThread(Thread.currentThread());
            ...
        }
    ...
    }

    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
    这句话可以将你的线程移动到后台。(该优先级低于主线程,避免与主线程竞争CPU)

    管理多线程

    这里以PhotoManager为例:

    1.既然是个管理者,最好是单例:(至于如何创建单例,不解释了)

    public class PhotoManager {
        ...
        static  {
            ...
            // Creates a single static instance of PhotoManager
            sInstance = new PhotoManager();
        }
       /**
         * Constructs the work queues and thread pools used to download
         * and decode images. Because the constructor is marked private,
         * it's unavailable to other classes, even in the same package.
         */
        private PhotoManager() {
        ...
        }
        ...

    2.启动一个照片下载任务,通过线程池,从队列中取一个runnable也就是任务对象:

    public class PhotoManager {
        ...
        // Called by the PhotoView to get a photo
        static public PhotoTask startDownload(
            PhotoView imageView,
            boolean cacheFlag) {
            ...
            // Adds a download task to the thread pool for execution
            sInstance.
                    mDownloadThreadPool.
                    execute(downloadTask.getHTTPDownloadRunnable());
            ...
        }

    3.自定义Handler来更新UI

        private PhotoManager() {
        ...
            // Defines a Handler object that's attached to the UI thread
            mHandler = new Handler(Looper.getMainLooper()) {
                /*
                 * handleMessage() defines the operations to perform when
                 * the Handler receives a new Message to process.
                 */
                @Override
                public void handleMessage(Message inputMessage) {
                    ...
                }
            ...
            }
        }

    4.决定线程池的参数:初始化的线程池大小和最大池大小

    首先ThreadPoolExcutor是android定义的类,不是java.

    那么线程池的大小如何决定?最大又该多少呢?

    答:省事点:通过Runtime.getRuntime().availableProcessors()

    public class PhotoManager {
    ...
        /*
         * Gets the number of available cores
         * (not always the same as the maximum number of cores)
         */
        private static int NUMBER_OF_CORES =
                Runtime.getRuntime().availableProcessors();
    }

    5.决定线程池的参数:空闲线程持续时间。(keep alive time),单位通过TimeUnit。

    6.任务队列:可以使用LinkedBlockingQueue<Runnable>

    public class PhotoManager {
        ...
        private PhotoManager() {
            ...
            // A queue of Runnables
            private final BlockingQueue<Runnable> mDecodeWorkQueue;
            ...
            // Instantiates the queue of Runnables as a LinkedBlockingQueue
            mDecodeWorkQueue = new LinkedBlockingQueue<Runnable>();
            ...
        }
        ...
    }

    7.好,下面进入创建线程池:

    private PhotoManager() {
            ...
       // Sets the amount of time an idle thread waits before terminating
       private static final int KEEP_ALIVE_TIME = 1;
       // Sets the Time Unit to seconds
       private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
       // Creates a thread pool manager
       mDecodeThreadPool = new ThreadPoolExecutor(
            NUMBER_OF_CORES,     // Initial pool size
            NUMBER_OF_CORES,    // Max pool size
            KEEP_ALIVE_TIME,
            KEEP_ALIVE_TIME_UNIT,
            mDecodeWorkQueue);
    }

    8.让线程池执行一个任务试试:ThreadPoolExecutor.execute()会将该任务加入到线程池的队列中。当一个空闲的线程变得可用时,Manager会将等待时间最长的任务运行在这个线程中。

    public class PhotoManager {
        public void handleState(PhotoTask photoTask, int state) {
            switch (state) {
                // The task finished downloading the image
                case DOWNLOAD_COMPLETE:
                // Decodes the image
                    mDecodeThreadPool.execute(
                            photoTask.getPhotoDecodeRunnable());
                ...
            }
            ...
        }
        ...
    }

    9.打断正在执行任务的某个或者所有线程

    public class PhotoManager {
        public static void cancelAll() {
            /*
             * Creates an array of Runnables that's the same size as the
             * thread pool work queue
             */
            Runnable[] runnableArray = new Runnable[mDecodeWorkQueue.size()];
            // Populates the array with the Runnables in the queue
            mDecodeWorkQueue.toArray(runnableArray);
            // Stores the array length in order to iterate over the array
            int len = runnableArray.length;
            /*
             * Iterates over the array of Runnables and interrupts each one's Thread.
             */
            synchronized (sInstance) {
                // Iterates over the array of tasks
                for (int runnableIndex = 0; runnableIndex < len; runnableIndex++) {
                    // Gets the current thread
                    Thread thread = runnableArray[taskArrayIndex].mThread;
                    // if the Thread exists, post an interrupt to it
                    if (null != thread) {
                        thread.interrupt();
                    }
                }
            }
        }
        ...
    }

    注意:大多数情况,Thread.interrupt()可以马上把线程打断掉。但是只能打断在等待的线程,不能打断CPU或者网络任务的线程。为了避免减缓或则锁住系统。你应该在尝试操作前,验证是否被打断。

    /*
    * Before continuing, checks to see that the Thread hasn't
    * been interrupted
    */
    if (Thread.interrupted()) {
        return;
    }
    ...
    // Decodes a byte array into a Bitmap (CPU-intensive)
    BitmapFactory.decodeByteArray(
            imageBuffer, 0, imageBuffer.length, bitmapOptions);
    ...
  • 相关阅读:
    UI: 操作导航控制器的视图控制器数组
    UI: 使用 UIViewController 展现和管理视图
    UI: 使用 UINavigationController 实现导航
    UI: 使用 UIActivityViewController 显示分享选项
    UI: 使用 UIActivityViewController 显示分享选项
    UI: 自定义 UISegmentedControl
    UI: UISegmentedControl 做简单选项分组及其自定义
    UI: UISlider 实现指定范围值的选择
    隧道目标识别实验过程(二)标准VOC数据集和制作后的数据集实验结果对比
    隧道目标识别实验过程(一)数据集的制作
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/3546418.html
Copyright © 2011-2022 走看看