Связь между основным потоком и рабочими потоками в Android

В моем самом первом проекте для Android я немного манипулирую данными, поэтому использую многопоточность.

В MainActivity я создал несколько объектов Runnable и использовал ExecutorService для запуска всех потоков. Насколько я понимаю, все потоки помещаются в очередь сообщений и выполняются по очереди. И поскольку основной поток уже находится в очереди, он будет выполнен перед запуском других потоков. Есть ли способ заставить основной поток дождаться завершения других потоков, а затем продолжить?

   @Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //call MyFunction here
}
private List<Pair[]> myFunction(int dataInput) throws InterruptedException {
    ExecutorService executorService = Executors.newFixedThreadPool(12);
    MyTask MyTask = new MyTask();
    for (int i = 0; i < gallerySize; ++i) {
        final int index = i;
        Runnable runnable = MyTask.runLongOperationWithThread(new MyTask.DataCallback(){
            @Override
            public void onSuccess(double[] scores) {
                // get data back to main thread
            }

            @Override
            public void onError(Exception ex) {
                //TODO: log this error out to file
            }
        });
        executorService.execute(runnable);
    }

    // try to get back all data from multi threading and do some operations
    return returnList;
}

Помогают ли в этом случае Looper и Handler?

И, пожалуйста, поправьте меня, если у меня есть какие-то недоразумения в концепции Android и потоковой передаче.

Спасибо.


person nghiduong90    schedule 12.06.2016    source источник
comment
Активность имеет runOnUiThread. Кроме того, обработчики могут получать сообщения, и если они работают в основном потоке Looper, сообщения будут обрабатываться в основном потоке. Итак, в основном прочтите документ: developer.android.com/training/multiple- темы /   -  person njzk2    schedule 12.06.2016


Ответы (1)


В Android остановка основного потока не рекомендуется. Система сообщит пользователю, что приложение не отвечает. Однако вы можете «уведомить» основной поток о том, что фоновый поток завершил свою работу. Как только основной поток узнает об этом, он что-то сделает. Это распространено в Android, для этого используется AsyncTask.

Однако AsyncTask используется для простого одного потока. В вашем случае одно из решений - объединить ExecutorService и AsyncTask. В doInBackground методе AsyncTask экземпляра, который вы создаете, используйте ExecutorService, как обычно, и дождитесь его завершения до shutdown(); awaitTermination() или invokeAll(). Прочтите этот вопрос / ответ для получения дополнительной информации. о том, как ждать ExecutorService, чтобы закончить.

private class WrappingTask extends AsyncTask<Void, Void, Exception> {
    protected Exception doInBackground(Void... args) {
        ExecutorService taskExecutor = Executors.newFixedThreadPool(12);
        for (. . .) {
            taskExecutor.execute(new MyTask(. . .));
        }
        taskExecutor.shutdown();
        try {
            taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            . . .
            return e;
        }
        return null;
    }

    protected void onPostExecute(Exception error) {
        // Notify the user that the task has finished or do anything else
        // and handle error
    }
 }

В случае длительной задачи

AsyncTask - удобный класс, упрощающий многопоточность и обмен данными (с основным потоком). Проблема для длительной задачи заключается в том, что пользователь может покинуть Activity (а затем снова прийти), или есть входящий вызов и т. Д. Если вы не будете осторожно обращаться с этим жизненным циклом действия, он настолько «опасен», что AsyncTask не справляется с этим.

Долгосрочная задача должна выполняться в Service. Обратите внимание, что Service также выполняется в основном потоке, поэтому подход будет таким же, если вы не используете _ 16_. В случае IntentService просто выполните все потоки (ранее в doInBackground) в методе onHandleIntent и дождитесь его там, этот метод вызывается в рабочем потоке.

Связь Service с Activity и поддержание согласованности состояния Activity на протяжении его жизненного цикла - долгая история. Лучше читайте документацию в "полной концентрации" за чашкой кофе: D. Это может помочь:

person fikr4n    schedule 12.06.2016
comment
Я где-то читал, что asyncTask недостаточно хорош для тяжелой обработки данных. В моем случае, поскольку я работаю с большим набором данных и мне нужно использовать параллельную обработку, может ли asyncTask помочь в решении этой задачи? - person nghiduong90; 12.06.2016
comment
@ nghiduong90 AsyncTask не подходит, потому что он не обрабатывает сам жизненный цикл Activity. Вы должны справиться с этим самостоятельно. И лучше использовать Сервис вместо Activity. Я обновил свой ответ. - person fikr4n; 12.06.2016