当前位置: 首页 > 面试题库 >

Android中的新Thread(task).start()VS ThreadPoolExecutor.submit(task)

印振国
2023-03-14
问题内容

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

所以现在我ThreadPoolExecutor在我的Application课堂上创建了一个包含5个线程的。这是代码:

public class App extends Application {

    private ThreadPoolExecutor mPool;

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

        mPool =  (ThreadPoolExecutor)Executors.newFixedThreadPool(5);
    }
}

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

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

因此,当我想在代码中运行异步任务时,我得到的实例,App并调用submitRunnableTask将可运行对象传递给它的方法。如您所见,我还检查线程池中是否有空闲线程来执行任务,否则,我将创建一个新线程(我不认为会发生这种情况,但是无论如何……我不会希望我的任务排在队列中并降低应用速度)。

onTerminate应用程序的回调方法中,我关闭了池。

所以我的问题是:这种模式是否比在代码中创建新线程更好?我的新方法有什么优点和缺点?会导致我尚不了解的问题吗?您能建议我一些比这更好的html" target="_blank">方法来管理我的异步任务吗?

PS:我在Android和Java方面有一定的经验,但是我并不是一名并发专家。)因此,在某些问题上可能有些方面我不太了解。任何建议将被认真考虑。


问题答案:

该答案假设您的任务很短

这样的模式是否比在代码中创建新的线程更好?

更好,但仍远非理想。您 仍在为短期任务创建线程 。相反,您只需要创建其他类型的线程池-例如by
Executors.newScheduledThreadPool(int corePoolSize)

行为上有什么区别?

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

第二个可以让您不要自己创建新线程。无需“预定”部分就可以实现此行为,但是您将不得不自己构造执行程序。构造函数是

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

各种选项使您可以微调行为。

如果有些任务很长…

我的意思是很长。与您的应用程序生命周期中的大部分时间一样(实时2路连接?服务器端口?多播侦听器?)。在这种情况下,将您Runnable的遗嘱执行人置于不利地位–标准的遗嘱执行人
并非 旨在应对这种情况,它们的性能将下降。

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

经验法则是

  • 如果 任务 ,请使用执行程序。
  • 如果 任务很长,请 确保您的执行程序可以处理它(即,它没有最大的池大小,或者没有足够的最大线程来处理多一个线程一段时间)
  • 如果这是一个需要始终与主线程一起运行的并行进程,请使用另一个线程。


 类似资料:
  • 在我的Android项目中,我有很多地方需要异步运行一些代码(web请求、对db的调用等)。这是运行时间不长的任务(最多几秒钟)。到目前为止,我一直在做这种事情,创建一个新线程,并通过任务传递给它一个新的runnable。但是最近我读了一篇关于Java中的线程和并发性的文章,我明白了为每个任务创建一个新线程并不是一个好的决定。 因此,现在我已经在我的类中创建了一个,它包含5个线程。代码如下: 我还

  • 本文向大家介绍Thread 类中的start() 和 run() 方法有什么区别?相关面试题,主要包含被问及Thread 类中的start() 和 run() 方法有什么区别?时的应答技巧和注意事项,需要的朋友参考一下 start()方法可以用来启动线程,调用该方法,会创建一个新的线程,然后内部执行run()方法;不能多次调用,否则会抛异常 直接调用run()方法,不会创建新的线程;可以进行多次调

  • 问题内容: 假设我们有以下两个Runnable: 那么这有什么区别: 和这个: 问题答案: 第一个示例:没有多个线程。两者都在单个(现有)线程中执行。没有线程创建。 只是实现接口并因此实现run()方法的类的两个不同对象。调用时,你正在当前线程中执行它。 第二个示例:两个单独的线程。 t1并且t2是该类的对象。当你调用时,它将启动一个新线程并在内部调用该run()方法r1以在该新线程中执行该方法。

  • 问题内容: 请解释以下代码的输出: 如果我致电,输出为: 如果我致电,输出为: 为什么会有这种不一致?请解释。 问题答案: 该方法启动一个新线程,该线程的入口点就是方法。如果直接调用run(),它将在同一线程中执行。假设调用将启动一个新的执行线程,则该方法可在其余主方法执行之后(如您的示例)被调用。 将您的main方法更改为调用并重复运行,您会发现有时它会输出: 有时它输出: 取决于Java选择如

  • 问题内容: 好标题说,和之间有什么区别 问题答案: 行为上,几乎没有。 但是,一旦有了一个实例,就可以向它提交多个任务,并使它们一个接一个地执行。您不能仅仅使用raw来做到这一点。

  • 问题内容: 假设我们有以下两个Runnable: 那么这有什么区别: 还有这个: 问题答案: 第一个示例:没有多个线程。两者都在单个(现有)线程中执行。没有线程创建。 和只是实现接口并因此实现方法的类的两个不同对象。调用时,你正在当前线程中执行它。 第二个示例:两个单独的线程。 并且是该类的对象。当你调用时,它将启动一个新线程并在内部调用该方法r1以在该新线程中执行该方法。