Android中的新线程(任务).start()VS ThreadPoolExecutor.submit(任务)

And*_*nik 15 java multithreading android asynchronous threadpoolexecutor

在我的Android项目中,我有很多地方需要异步运行一些代码(Web请求,调用db等).这不是长时间运行的任务(最多几秒钟).到目前为止,我正在创建一个新线程,通过任务传递一个新的runnable.但是最近我读了一篇关于Java中的线程和并发的文章,并且理解为每个任务创建一个新的Thread并不是一个好的决定.

所以现在我ThreadPoolExecutor在我的Application类中创建了一个包含5个线程的类.这是代码:

public class App extends Application {

    private ThreadPoolExecutor mPool;

    @Override
    public void onCreate() {
        super.onCreate();

        mPool =  (ThreadPoolExecutor)Executors.newFixedThreadPool(5);
    }
}
Run Code Online (Sandbox Code Playgroud)

我还有一种方法可以将Runnable任务提交给执行者:

public void submitRunnableTask(Runnable task){
    if(!mPool.isShutdown() && mPool.getActiveCount() != mPool.getMaximumPoolSize()){
        mPool.submit(task);
    } else {
        new Thread(task).start();
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,当我想在我的代码中运行异步任务时,我得到实例App并调用submitRunnableTask将runnable传递给它的方法.正如你所看到的,我也检查一下,如果线程池有自由线程来执行我的任务,如果没有,我创建一个新线程(我不认为这会发生,但无论如何......我不知道我希望我的任务在队列中等待并减慢应用程序).

onTerminateApplication 的回调方法中,我关闭了池.

所以我的问题如下:这种模式比代码中创建新的线程更好吗?我的新方法有哪些优点和缺点?它会引起我不知道的问题吗?你能告诉我一些比这更好的东西来管理我的异步任务吗?

PS我在Android和Java方面有一些经验,但我远不是一个并发大师.所以可能有些方面我在这类问题中不太了解.任何建议将被认真考虑.

Ord*_*ous 20

这个答案假设您的任务很短

这种模式比代码中创建新的Thread更好吗?

它更好,但它仍然远非理想.您仍在为简短任务创建线程.相反,您只需要创建一个不同类型的线程池 - 例如Executors.newScheduledThreadPool(int corePoolSize).

行为有什么不同?

  • A FixedThreadPool将始终具有一组要使用的线程,如果所有线程都忙,则新任务将被放入队列中.
  • ScheduledThreadPoolExecutors类创建的(默认)具有它保持的最小线程池,即使在空闲时也是如此.如果新任务进入时所有线程都忙,它会为它创建一个新线程,并在完成后60秒处理该线程,除非再次需要它.

第二个可以让你自己不创建新的线程.这种行为可以在没有"计划"部分的情况下实现,但是您必须自己构建执行程序.构造函数是

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue)
Run Code Online (Sandbox Code Playgroud)

各种选项允许您微调行为.

如果有些任务很长......

我的意思是很长 与大多数应用程序生命周期一样(实时双向连接?服务器端口?多播侦听器?).在这种情况下,将您Runnable的遗嘱执行人放入是有害的 - 标准执行人并非旨在应对它,而且他们的表现会恶化.

想想你的固定线程池 - 如果你有5个长时间运行的任务,那么任何新任务都会产生一个新线程,完全破坏池的任何可能的收益.如果您使用更灵活的执行程序 - 某些线程将被共享,但并非总是如此.

经验法则是

  • 如果这是一项简短的任务 - 使用执行者.
  • 如果这是一个很长的任务 - 确保您的执行程序可以处理它(即它没有最大池大小,或者有足够的最大线程来处理1个以上的线程已经消失了一段时间)
  • 如果它是一个需要始终与主线程一起运行的并行进程 - 请使用另一个Thread.


Tan*_*nay 6

回答你的问题 - 是的,使用Executor比创建新线程更好,因为:

  1. Executor提供了一系列不同的线程池.它允许重用已经存在的线程,这提高了性能,因为线程创建是一项昂贵的操作.
  2. 如果线程死亡,Executor可以用新线程替换它而不影响应用程序.
  3. 对多线程策略的更改要容易得多,因为只需要更改Executor实现.