如何承诺完成多个线程?

时间:2017-12-10 11:08:08

标签: java android multithreading executorservice

我是java中MultiThreading概念的新手 这个问题的标题可能与之前关于这个主题的问题有相似之处,但是,尽管看了答案,我仍然成功地完成了以下任务:

在MainActivity上说我有一个嵌套的for循环。在内部循环中,我正在运行另一个类的方法,该方法将接口作为回调,如下所示:

MainActivity.java

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_display_prices, container, false);

    return v;

    for (i = 0; i < 10; i++) {

        for (i = 0; i < 4; i++){
              CategoryItemsDataSource.getCategoryItemsData(url, new CategoryItemsDataSource.OnCategoryItemsDataArrived() {
                        @Override
                        public void onCategoryItemsDataArrived(List<ProductItem> data, Exception e) {
                             getActivity.runOnUiThread(new Runnable() {

                                   //display retrieved data on UIThread...
                             });

                        }
              });
        }
    }

}

CategoryItemDataSource.java

 public class CategoryItemsDataSource {

public interface OnCategoryItemsDataArrived {
    void onCategoryItemsDataArrived(List<ProductItem> data, Exception e);
}

public static void getCategoryItemsData(final String[] url, final OnCategoryItemsDataArrived listener){

    ExecutorService service = Executors.newSingleThreadExecutor();
    service.execute(new Runnable() {
        @Override
        public void run() {
            try {
                List<ProductItem> data = new ArrayList<>();
                //retreiving data from web and appending to List<> Data....
                }
                listener.onCategoryItemsDataArrived(data, null);
            } catch (Exception e) {
                e.printStackTrace();
                listener.onCategoryItemsDataArrived(null, e);
            }
        }
    });
    service.shutdown();
}

我不知道如何在MainActivity中从CategoryItemDataSource类[I.E,如果我需要的话]访问ExecutorService实例。因此,我怎么想确保/保证完成内循环中生成的所有几个线程?

2 个答案:

答案 0 :(得分:1)

创建一个计数器变量;在循环中,每次将新任务提交给执行程序时递增计数器。在onCategoryItemsDataArrived方法中,减少该计数器;当它变为零时,所有任务都完成。提供对计数器的原子访问:使用AtomicIntegersynchronized语句。

答案 1 :(得分:0)

  

我不知道如何在MainActivity中从CategoryItemDataSource类[I.E,如果我需要的话]访问ExecutorService实例。因此,我怎么想确保/保证完成内循环中生成的所有几个线程?

有几种方法可以做到这一点,但最好的方法是getCategoryItemsData(...)方法返回Future命令返回的service.submit(...)对象(而不是service.execute(...) })。然后,您可以将这些Future保存在数组中,并在其上调用future.get(...)以等待它们完成。如果您自己管理线程,则执行此操作类似于调用thread.join()

类似的东西:

int numJobs = 4;
// this might need to be Future<Void> or something
Future<?>[] futures = new Future<>[numJobs];
for (i = 0; i < numJobs; i++) {
    futures[i] = CategoryItemsDataSource.getCategoryItemsData(...);
}
for (Future<?> future : futures) {
    // waits for each of the jobs to finish, you'll need to handle the exceptions
    future.get();
}

但有一点很奇怪,那就是你每次都要创建一个新的ExecutorService。我怀疑你想要那样做。我会在CategoryItemsDataSource中创建一项服务作为字段,然后让每个getCategoryItemsData(...)次调用将其作业提交给同一服务。