【问题标题】:How to run a code when all threads are done所有线程完成后如何运行代码
【发布时间】:2016-06-21 07:22:17
【问题描述】:

我是线程新手,我在堆栈溢出中经历了许多帖子,并为我的问题找到了许多解决方案,但我不确定哪个最适合哪种情况。

首先,我的问题是我想更新一个 JSON 文件 当所有线程都在特定路径上完成位图生成时 我可以获得所有这些图像并更新 JSON 文件。所以在 简单的词我想在所有线程都完成后运行一些代码 执行和主要要求是我不希望我的 main 被阻塞。

我发现了什么

  • 线程。加入
  • excutorServive
  • android-priority-jobQueue (link)
  • 线程池中的互斥体(如果还有其他的,请告诉我)

我很困惑哪一个是解决我的问题的最佳方法。如果有的话 那里的android专家可以总结一下,以关注这两个 scenerio 什么是 android 中最好的。

  • 等到所有线程完成
  • 不要等待,当一切都完成后得到通知

【问题讨论】:

    标签: android multithreading executorservice


    【解决方案1】:

    你可以为你的线程设置计数器,在每个线程完成后检查有多少已经完成,如果没有完成,增加完成的线程数,最后一个完成的线程将运行这段代码。

    【讨论】:

    • 你能不能在用法上再描述一下。我不知道将运行多少线程。它也是一个变量。因为我不知道会有多少位图生成。第二件事我希望它完全独立于我的应用程序的模块。如何知道一个线程已经完成?为此,我需要在一个线程中有一个 while 循环(如果我错了,请纠正我)
    • @RATHI 扩展了 KgaboL 的答案,在启动线程的同时,您可以增加一个计数器(如果需要,可以在静态类中设置)。当线程结束时,减少该计数器,并检查它是否等于 0。当它为零时,这意味着所有线程都消失了。您仍然需要考虑当不再需要一组线程时会发生什么(例如,延迟加载一些不再在屏幕上显示的图像),例如确保最终作业不会执行,除非您再次创建线程,或类似的东西。
    • @Korcholis 感谢您的回答,这种方法可以使用什么,我正在考虑使用线程池执行器。实际上我对此感到困惑,以后不想再跳到另一种方法。
    • @RATHI 寻找那里的实现。我个人会选择创建一个以单例方式处理线程生成和管理的类——但谁知道呢,我是单例的粉丝!无论如何,在 Android 中(几乎任何地方,甚至网络),即使用户关闭应用程序,您仍然需要考虑是否有必要完成线程,在这种情况下,像 Gpuschka 建议的意图服务可能是 the 选项
    【解决方案2】:

    你可以这样做。

    在你的帖子中:

    private Runnable runnableThread= new Runnable() {
        @Override
        public void run() {
            try {
                if (lastThreadDone){
                    handler.sendEmptyMessage("SUCCESS");
                }
            }
            catch (Exception ex) {
                throws ex;
            }
        }
    };
    

    lastThreadDone 是布尔值,如果该过程完成,它将变为 true,这取决于您如何实现它。

    然后在你的处理程序中:

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            try {
                switch (msg.what) {
                    case "SUCCESS": {
                        // your code here 
                        break;
                    }
                    case "FAIL":
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex) {
                throw ex;
            }
            super.handleMessage(msg);
        }
    };
    

    【讨论】:

    • 这就是我认为您将如何知道最后一个线程已完成的问题?排队的最后一个线程并不总是最后一个执行的线程。不是吗?假设我已经启动了 6 个线程,并且在所有这六个线程结束时我应该收到此消息。所以我能想到的是我可以在计数上有一个互斥锁,当每个线程完成执行时,我可以减少该计数,并且当最后一个线程在那时运行时,我可以将此消息发送给处理程序。但这需要我需要处理的大量并发性。
    • 我认为这是一个众所周知的问题,应该有一些很好的选择可以在 android 中轻松处理这个问题。如果我从 android 中排除太多,请纠正我。 :P
    • 最像现在的线程有限制。我建议尝试 Asynctask 更适合您的问题的解决方案,请参阅此处stackoverflow.com/a/24228697/5870896
    • 我认为当你有一些 2 或 3 个任务时应该使用异步线程,我的意思是当你不寻找太多并行性并且默认情况下 asynctask 串行运行时。所以我认为这对我来说不是一个好的选择。
    • 通常在主线程上,图像再现生成每个需要 2 到 3 秒。一次可以生成多达 20 个图像
    【解决方案3】:

    我会使用completion service,然后轮询直到所有任务完成。完成后,json 文件将被更新。问题是您需要异步执行此操作,否则您可能会阻止用户界面。因此,我会将带有完成服务的工作封装在intent service 中。如果您需要更新用户界面,您可以从意图服务发布local broadcasts

    更多案例

    • 等到所有线程完成

      • 仅当您已经在意图服务或异步任务等后台线程上时才执行此操作
    • 当一切都完成时不要等待并得到通知

      • 表示上述情况。异步执行工作并通过广播通知 ui 或某些侦听组件,content observershandlers 或“onPostExecute”(如果您使用的是async task)。

    【讨论】:

    • 感谢您的回答,这看起来很有希望,但从该线程来看,“基本上,如果您想并行执行多个任务,然后按完成顺序处理它们,您可以使用 CompletionService。所以,如果我执行 5 个作业,CompletionService 会给我第一个完成的作业”,我不需要每个线程顺序的结果,我想知道它们已经完成
    • intent 服务中的线程池也是一个不错的选择吗?
    • 当然,只要符合目的。至于完成服务,它确实会返回第一个完成的任务,但您可以拉出与提交任务一样多的次数。当拉取计数器与提交计数器匹配时,您就知道每个任务都已执行。使用意图服务时,请记住意图服务在执行后被销毁,因此不要依赖任何状态。
    • 没让你在最后一行。
    • 还有一件事,如果服务不是该服务的生成线程的优先级,那么与主线程相比,完成所有线程所需的时间会更少线程池?
    猜你喜欢
    • 2022-01-10
    • 1970-01-01
    • 2015-03-25
    • 2014-05-22
    • 2020-12-15
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 2013-10-23
    相关资源
    最近更新 更多