HandlerThread vs Executor - Когда один из них уместнее другого?
Мне просто любопытно, есть ли времена, когда я должен выбрать Executor
через HandlerThread
, Есть ли моменты, когда один превосходит другой, или я должен просто придерживаться HandlerThread
? В моем случае, я сейчас слушаю ServerSocket
для соединений и обработки каждого запроса в отдельном потоке, созданном Executor
, Несмотря на то, что я привел конкретный пример, я на самом деле просто ищу случаи, когда один из них более уместен, чем другой. Тем не менее, я приветствую комментарии о моем дизайне.
2 ответа
Класс Executor более мощный и может использовать пул потоков, тогда как каждый обработчик ссылается на один поток. Исполнитель позволяет вам получить все запланированные задания и отменить их, если хотите. С другой стороны, Обработчик не будет отвечать на простые вопросы, такие как, сколько задач ожидает, или давать ссылку на все ожидающие задачи. Я полагаю, что одна из причин того, что обработчик более ограничен, заключается в том, что Android предоставляет вам доступ к основному обработчику, который он использует для пользовательского интерфейса, и вы действительно можете испортить ОС, если вы начали отменять задачи ОС.
В общем, если вам нужен пул потоков или много энергии, используйте Executor. Если вам просто нужен хороший фоновый поток для запуска одной задачи за раз, используйте обработчик. Например, когда я хочу запросить свою базу данных, я действительно хочу, чтобы за один раз выполнялся только один запрос, и я не хочу генерировать 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, когда вы закончите с ним, иначе он будет ждать вечно
Я не буду следовать примеру кода в ответе 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 и ниже разделяют искусственно ограниченное количество процессорного времени с помощью группы 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);
поднять свой фоновый поток из cgroup.