Android 使用多个线程池执行器

Posted

技术标签:

【中文标题】Android 使用多个线程池执行器【英文标题】:Android using multiple threadpoolexecutors 【发布时间】:2017-06-28 16:21:02 【问题描述】:

嘿,这是一个有趣的问题。我在我的 android 项目中使用了很多带有 sqlite 的 sql 操作。为此,我使用线程池来重用现有资源。线程池长这样:

final int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor threadPoolExecutor= new ThreadPoolExecutor(NUMBER_OF_CORES*2,NUMBER_OF_CORES*2,1L, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(12,true),new PriorityThreadFactory(Process.THREAD_PRIORITY_BACKGROUND),new RejectedThread(context));



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 
                    android.os.Process.setThreadPriority(mThreadPriority);
                 catch (Throwable t) 

                
                runnable.run();
            
        ;
        return new Thread(wrapperRunnable);
    

    




public class RejectedThread implements RejectedExecutionHandler 

    MyLogger myLogger;

    public RejectedThread(Context context) 
        this.myLogger=new MyLogger(RejectedThread.class.getSimpleName(), context);
    

    @Override
    public void rejectedExecution(Runnable worker, ThreadPoolExecutor executor) 
        this.myLogger.info("Execution rejected for: "+worker.toString());
    

我还在为我在数据库中进行的每个 CRUD(创建-读取-更新-删除)操作(由上面的线程池执行)创建一个新的 Runnable。这是问题,除了用于 sql 操作的线程池之外,我还需要一个线程池来执行记录器操作,以记录我制作的其余函数的系统行为。有没有办法防止任何粉碎/(资源不足),因为我正在使用两个或多个线程池执行器(分开分配,用于不同目的并且从不在另一个线程池执行器上执行线程池执行器) ?

【问题讨论】:

这一切似乎都是多余的。为什么记录器操作需要线程池?另外,为什么不能使用 AsyncTask 类中的现有执行程序?你有什么问题吗? 所有CRUD 操作无论如何都不会同步,这意味着运行线程池不是真正的优势吗? [Okas] 所有这些日志都发送到服务,因此此操作始终在后台进行。我正在尝试完成类似:Firebase Crash Reporting (firebase.google.com/docs/crash) 但使用我的个人服务器且功能较少的事情。 [Mark Keen] 我认为我有很大的进步,因为所有的 crud 操作(对我来说)都是在我总是收到推送通知的地方完成的。根据我收到的消息,我的应用知道要执行什么操作,这样我的 ui 线程就空闲了。 对不起我的英语不好... 【参考方案1】:

我认为总的来说你的想法很好,但是你的实现有点低效。

试着自己回答这些问题:

为什么需要两个线程池? 您真的需要两个线程池吗? 为什么将 CORE 大小设置为 NUMBER_OF_CORES*2? 为什么将 MAX 大小设置为 NUMBER_OF_CORES*2? 您真的需要覆盖线程优先级吗?

根据我的经验,上述并发症都不是真正必要的。

例如,在我的所有应用程序中,我使用BackgroundThreadPoster 类的单个实例来将工作卸载到后台线程。类很简单:

/**
 * A single instance of this class should be used whenever we need to post anything to a (random) background thread.
 */
public class BackgroundThreadPoster 

    ExecutorService mExecutorService = Executors.newCachedThreadPool();

    public void post(Runnable runnable) 
        mExecutorService.execute(runnable);
    

Executors.newCachedThreadPool() 返回的默认预配置实现就像魔术一样工作,我从未遇到过任何自定义其参数的需要。

可以在此处找到使用此方法的完整教程应用程序:https://github.com/techyourchance/android_mvc_tutorial

也许这对你也有用?

【讨论】:

感谢您的回答!

以上是关于Android 使用多个线程池执行器的主要内容,如果未能解决你的问题,请参考以下文章

Android3.0以后,Asynctask在没开线程池的情况下会怎么排队执行

Android 线程池的封装

Android 对线程封装了:AsyncTask, HandlerThread和线程池。 有知道这三个如何选择吗?

Android AsyncTask内部线程池异步执行任务机制简要分析

Android 四种线程池

Android线程与线程池