HandlerThread vs Executor - Когда один из них уместнее другого? - PullRequest
35 голосов
/ 18 сентября 2011

Мне просто любопытно, есть ли моменты, когда я должен выбрать Executor вместо HandlerThread. Есть ли моменты, когда один превосходит другой, или я действительно должен просто придерживаться HandlerThread? В моем случае я слушаю ServerSocket для соединений и обрабатываю каждый запрос в отдельном потоке, созданном Executor. Несмотря на то, что я привел конкретный пример, я на самом деле просто ищу случаи, когда один из них более уместен, чем другой. Тем не менее, я приветствую комментарии о моем дизайне.

Ответы [ 2 ]

49 голосов
/ 19 сентября 2011

Класс Executor более мощный и может использовать пул потоков, тогда как каждый обработчик ссылается на один поток. Исполнитель позволяет вам получить все запланированные задания и отменить их, если хотите. С другой стороны, Обработчик не будет отвечать на простые вопросы, такие как, сколько задач ожидает, или давать ссылку на все ожидающие задачи. Я полагаю, что одна из причин того, что обработчик более ограничен, заключается в том, что Android дает вам доступ к основному обработчику, который он использует для пользовательского интерфейса, и вы действительно можете испортить ОС, если вы начали отменять задачи ОС.

В общем, если вам нужен пул потоков или много энергии, используйте Executor. Если вам просто нужен красивый фоновый поток для запуска одной задачи за раз, используйте Handler. Например, когда я хочу запросить свою базу данных, я действительно хочу, чтобы за один раз выполнялся только один запрос, и я не хочу генерировать ANR, поэтому я использую обработчик, работающий в фоновом потоке, для выполнения моих запросов.

Я считаю, что ваш выбор исполнителя звучит уместно, поскольку вы хотите обрабатывать несколько входящих запросов одновременно, а обработчик может выполнять только один запрос за раз.

ОБНОВЛЕНИЕ: Как создать обработчик, работающий в фоновом потоке:

В вашем конструкторе или onCreate напишите следующее, очевидно, вы можете установить приоритет на то, что вам нравится:

public class MyClass {

    private Handler mBgHandler;

    public MyClass() {
        HandlerThread bgThread = new HandlerThread("My-Background-Handler");
        bgThread.start();
        mBgHandler = new Handler(bgThread.getLooper());
    }
}

ОБНОВЛЕНИЕ: не забывайте выходить () или выходить из вашего HandlerThread () или выходить из него (), когда вы закончите с ним, в противном случае он будет ждать вечно

13 голосов
/ 08 января 2013

Я не буду следовать примеру кода в ответе satur9nine по состоянию на 22 декабря 2011 года.

Thread.MIN_PRIOROTY сопоставлен с android.os.Process.THREAD_PRIORITY_LOWEST. Цитата

Самый низкий доступный приоритет потока. Только для тех, кто действительно, действительно не хочет бежать, если что-то еще происходит.

Я бы хотя бы использовал android.os.Process.THREAD_PRIORITY_BACKGROUND, вот так:

HandlerThread bgThread = new HandlerThread("handler name");
Process.setThreadPriority(bgThread.getThreadId(), Process.THREAD_PRIORITY_BACKGROUND);
bgThread.start();
mBgHandler = new Handler(bgThread.getLooper());

Это назначает потоку фоновый приоритет Android по умолчанию.

В настоящее время потоки с приоритетом Process.THREAD_PRIORITY_BACKGROUND и ниже разделяют искусственно ограниченное количество процессорного времени с помощью cgroup Linux, см., Например, здесь . Если фоновая задача не просто ожидает ввода-вывода, но выполняет реальные вычисления, я бы рассмотрел вопрос об увеличении ее приоритета с помощью android.os.Process.THREAD_PRIORITY_MORE_FAVORABLE, который (в настоящее время) перемещает ее из фоновой группы, хотя по-прежнему не подвергает опасности пользовательский интерфейс и деятельность в реальном времени.

Обновление: Ответ satur9nine был безмолвно пересмотрен 2013-янв-08, чтобы больше не устанавливать самый низкий возможный приоритет. HandlerThread теперь будет неявно иметь приоритет android.os.Process.THREAD_PRIORITY_BACKGROUND. Это означает, что теперь он получает приоритет фоновой задачи по умолчанию, но он по-прежнему ограничен в использовании искусственного максимума 10% процессорного времени вместе со всеми другими фоновыми задачами, которые могут существовать. Если это не желательно, используйте мой код выше, например. с

Process.setThreadPriority(bgThread.getThreadId(),
                          Process.THREAD_PRIORITY_BACKGROUND + Process.THREAD_PRIORITY_MORE_FAVORABLE);

чтобы вывести фоновый поток из группы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...