如何在安卓中使用线程池(ThreadPoolExecutor)

来源:互联网 发布:mac cocos2dx lua 编辑:程序博客网 时间:2024/06/09 21:30

如何在安卓中使用线程池(ThreadPoolExecutor)

标签(空格分隔): 翻译计划


原文链接地址:Using ThreadPoolExecutor in Android

这篇文章将会覆盖线程池、线程池执行者、和怎么把他们使用到安卓里面。我们将会介绍这些主题,并且会附有许多示例代码。

线程池(Thread Pools)

一个线程池管理者一个工作线程池(线程池确定的个数取决于我们如何实现的)

一个任务队列保持着等待的任务,这些任务将会被线程池中的等待线程执行。生产者把任务添加到队列中,而工作线程作为消费者,只要有空闲的线程准备好执行任务,就从任务队列中取出任务并且消耗掉它。

线程执行者(ThreadPoolExecutor)

ThreadPoolExecutor则使用线程池中的一个线程来执行给定的任务
创建一个线程执行者:

 ThreadPoolExecutor executor = ThreadPoolExecutor( int corePoolSize,        int maximumPoolSize,        long keepAliveTime,        TimeUnit unit,        BlockingQueue<Runnable> workQueue);

这些参数的含义

  • 1、corePoolSize
    • 线程池中的最小线程个数,最初的线程池个数初始化是0个,但是当我们把任务添加到队列中的时候,一个新的线程将会被创建,如果有空线程,但是线程数低于corePoolSize,那么新的线程将会被继续创建
  • 2、maximumPoolSize
    • 线程池中允许创建的最大线程个数,如果这个数字超过了corePolSize,并且currentPoolSize>=corePoolSize,那么只有当队列满的时候才会去创建新的工作线程。
  • 3、keepAliveTime
    • 线程存活时间,当线程数大于核心线程(工作线程),那么非核心线程(多于的空闲线程)将等待新的任务,如果这些线程在该参数定义的时间内没有得到任务去执行,将会被销毁。
  • 4、unit
    • 线程存活时间keepAliveTime的时间单位
  • 5、workQueue
    • 工作队列,将会持有持续运行任务,这里将会展现BlockingQueue

安卓和Java中为什么会用到线程池

  • 1、这是一个强大的任务执行框架,支持队列中的任务添加,任务取消和任务优先级排序
  • 2、它可以减少线程创建的开销,因为他会在线程池中管理所需要的线程

在安卓中使用ThreadPoolExecutor

首先,创建一个PriorityThreadFactory

public class PriorityThreadFactory implements ThreadFactory {    private final int mThreadPriority;    public PriorityThreadFactory(int threadPriority) {        mThreadPriority = threadPriority;    }    @Override    public Thread newThread(final Runnable runnable) {        Runnable wrapperRunnable = new Runnable() {            @Override            public void run() {                try {                    Process.setThreadPriority(mThreadPriority);                } catch (Throwable t) {                }                runnable.run();            }        };        return new Thread(wrapperRunnable);    }}

创建一个MainThreadExecutor

public class MainThreadExecutor implements Executor {    private final Handler handler = new Handler(Looper.getMainLooper());    @Override    public void execute(Runnable runnable) {        handler.post(runnable);    }}

创建一个DefaultExecutorSupplier

/** Singleton class for default executor supplier*/public class DefaultExecutorSupplier{    /*    * Number of cores to decide the number of threads    */    public static final int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();    /*    * thread pool executor for background tasks    */    private final ThreadPoolExecutor mForBackgroundTasks;    /*    * thread pool executor for light weight background tasks    */    private final ThreadPoolExecutor mForLightWeightBackgroundTasks;    /*    * thread pool executor for main thread tasks    */    private final Executor mMainThreadExecutor;    /*    * an instance of DefaultExecutorSupplier    */    private static DefaultExecutorSupplier sInstance;    /*    * returns the instance of DefaultExecutorSupplier    */    public static DefaultExecutorSupplier getInstance() {       if (sInstance == null) {         synchronized(DefaultExecutorSupplier.class){                                                                               sInstance = new DefaultExecutorSupplier();              }        return sInstance;    }    /*    * constructor for  DefaultExecutorSupplier    */     private DefaultExecutorSupplier() {        // setting the thread factory        ThreadFactory backgroundPriorityThreadFactory = new                 PriorityThreadFactory(Process.THREAD_PRIORITY_BACKGROUND);        // setting the thread pool executor for mForBackgroundTasks;        mForBackgroundTasks = new ThreadPoolExecutor(                NUMBER_OF_CORES * 2,                NUMBER_OF_CORES * 2,                60L,                TimeUnit.SECONDS,                new LinkedBlockingQueue<Runnable>(),                backgroundPriorityThreadFactory        );        // setting the thread pool executor for mForLightWeightBackgroundTasks;        mForLightWeightBackgroundTasks = new ThreadPoolExecutor(                NUMBER_OF_CORES * 2,                NUMBER_OF_CORES * 2,                60L,                TimeUnit.SECONDS,                new LinkedBlockingQueue<Runnable>(),                backgroundPriorityThreadFactory        );        // setting the thread pool executor for mMainThreadExecutor;        mMainThreadExecutor = new MainThreadExecutor();    }    /*    * returns the thread pool executor for background task    */    public ThreadPoolExecutor forBackgroundTasks() {        return mForBackgroundTasks;    }    /*    * returns the thread pool executor for light weight background task    */    public ThreadPoolExecutor forLightWeightBackgroundTasks() {        return mForLightWeightBackgroundTasks;    }    /*    * returns the thread pool executor for main thread task    */    public Executor forMainThreadTasks() {        return mMainThreadExecutor;    }}

现在在你的代码逻辑中使用吧

/** Using it for Background Tasks*/public void doSomeBackgroundWork(){  DefaultExecutorSupplier.getInstance().forBackgroundTasks()    .execute(new Runnable() {    @Override    public void run() {       // do some background work here.    }  });}/** Using it for Light-Weight Background Tasks*/public void doSomeLightWeightBackgroundWork(){  DefaultExecutorSupplier.getInstance().forLightWeightBackgroundTasks()    .execute(new Runnable() {    @Override    public void run() {    // do some light-weight background work here.    }  });}/** Using it for MainThread Tasks*/public void doSomeMainThreadWork(){  DefaultExecutorSupplier.getInstance().forMainThreadTasks()    .execute(new Runnable() {    @Override    public void run() {       // do some Main Thread work here.    }  });}

通过这种方式,我们可以创建不同的线程池来服务于网络任务/IO任务/(后台)耗时任务、还有其他任务。

如何取消任务

当我们取消一个任务的时候,我们需要得到一个Future,而不是直接执行,因此我们需要使用submit,这样将会返回一个Future,然后我们就可以使用返回回来的Future来取消任务.

/** Get the future of the task by submitting it to the pool*/Future future = DefaultExecutorSupplier.getInstance().forBackgroundTasks()    .submit(new Runnable() {    @Override    public void run() {      // do some background work here.    }});/** cancelling the task*/future.cancel(true); 

如何对一个任务设置优先级

假设一个任务队列中有20个任务,而我们创建的线程池只有四个可用于工作的线程,我们可以基于优先级来执行任务,毕竟我们一次只能执行4个任务。

假设我们需要在队列中首先执行最后一个任务,我们可以为这个线程设置IMMEDIATE优先级,以便于我们在队列中获取新任务的时候,将会执行此任务(因为这个标志的任务具有最高优先级)

要设置任务的优先级,我们需要创建一个线程池执行器

创建枚举优先级

/** * Priority levels */public enum Priority {    /**     * NOTE: DO NOT CHANGE ORDERING OF THOSE CONSTANTS UNDER ANY CIRCUMSTANCES.     * Doing so will make ordering incorrect.     */    /**     * Lowest priority level. Used for prefetches of data.  低级优先级     */    LOW,    /**     * Medium priority level. Used for warming of data that might soon get visible.  中端优先级     */    MEDIUM,      /**     * Highest priority level. Used for data that are currently visible on screen.  高优先级     */    HIGH,    /**     * Highest priority level. Used for data that are required instantly(mainly for emergency).  最高优先级     */    IMMEDIATE;}

创建一个优先级线程

public class PriorityRunnable implements Runnable {    private final Priority priority;    public PriorityRunnable(Priority priority) {        this.priority = priority;    }    @Override    public void run() {      // nothing to do here.    }    public Priority getPriority() {        return priority;    }}

创建一个PriorityThreadPoolExecutor(优先级线程执行者)继承于ThreadPoolExecutor,我们还需要创建一个PriorityFutureTask,实现Comparable接口

public class PriorityThreadPoolExecutor extends ThreadPoolExecutor {   public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,         TimeUnit unit, ThreadFactory threadFactory) {        super(corePoolSize, maximumPoolSize, keepAliveTime, unit,new PriorityBlockingQueue<Runnable>(), threadFactory);    }    @Override    public Future<?> submit(Runnable task) {        PriorityFutureTask futureTask = new PriorityFutureTask((PriorityRunnable) task);        execute(futureTask);        return futureTask;    }    private static final class PriorityFutureTask extends FutureTask<PriorityRunnable>            implements Comparable<PriorityFutureTask> {        private final PriorityRunnable priorityRunnable;        public PriorityFutureTask(PriorityRunnable priorityRunnable) {            super(priorityRunnable, null);            this.priorityRunnable = priorityRunnable;        }        /*         * compareTo() method is defined in interface java.lang.Comparable and it is used         * to implement natural sorting on java classes. natural sorting means the the sort          * order which naturally applies on object e.g. lexical order for String, numeric          * order for Integer or Sorting employee by there ID etc. most of the java core          * classes including String and Integer implements CompareTo() method and provide         * natural sorting.         */        @Override        public int compareTo(PriorityFutureTask other) {            Priority p1 = priorityRunnable.getPriority();            Priority p2 = other.priorityRunnable.getPriority();            return p2.ordinal() - p1.ordinal();        }    }}

首先,在DefaultExecutorSupplier,而不是ThreadPoolExecutor中,向一下使用方式使用PriorityThreadPoolExecutor.

public class DefaultExecutorSupplier{private final PriorityThreadPoolExecutor mForBackgroundTasks;private DefaultExecutorSupplier() {        mForBackgroundTasks = new PriorityThreadPoolExecutor(                NUMBER_OF_CORES * 2,                NUMBER_OF_CORES * 2,                60L,                TimeUnit.SECONDS,                backgroundPriorityThreadFactory        );    }}

给一个如何给一个任务设置优先级的例子

/** do some task at high priority*/public void doSomeTaskAtHighPriority(){  DefaultExecutorSupplier.getInstance().forBackgroundTasks()    .submit(new PriorityRunnable(Priority.HIGH) {    @Override    public void run() {      // do some background work here at high priority.    }});}

通过这种方式,我们就可以创建一个具有优先级的任务,上述所有使用方式同样适用于Java Applications

这里给一个我自己封装的安卓网络工作的依赖库Android Networking Library

如果想知道更详细的实现,可以查看DefaultExecutorSupplier.java这个类在Android Networking here.

我希望这些知识对于你有些帮助

感谢您阅读本文。
如果您发现它有用,请务必点击下面的❤推荐这篇文章。

如果想知道更多的关于程序设计方面的知识, follow me and Mindorks ,以便于我们更新新的技术文章的时候会通知到你。

Check out all the Mindorks best articles here.

Also, Let’s become friends on Twitter, Linkedin, Github and Facebook.

当然了最后的这些推荐都是需要翻墙的,这个就需要大家墙一下了哈.这里推荐给大家一个翻墙的网址,需要收费的,但是非常便宜的(最低的套餐一个月15G/1.5元 一年才18(现在搞活动)),可以看一下

原创粉丝点击