Android知识Android开发经验谈Android开发

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

2017-06-28  本文已影响304人  菜鸟_一枚

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

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


原文链接地址:Using ThreadPoolExecutor in Android

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

线程池(Thread Pools)

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

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

线程执行者(ThreadPoolExecutor)

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

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

这些参数的含义

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

在安卓中使用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<PriorityFutureTask>接口

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(现在搞活动)),可以看一下

上一篇 下一篇

猜你喜欢

热点阅读