Я не уверен, будет ли для этого библиотека, так как Android уже предоставляет высокоуровневые строительные блоки для того, чего вы пытаетесь достичь.
Обработчик
Если я вас правильно понял, вы хотите публиковать задачи из любого потока, чтобы ставить их в очередь и выполнять по отдельности в отдельном потоке. Это то, для чего предназначен Android Handler
.
Ключевые черты Handler, Looper и MessageQueue
- Обработчик привязан к одному
Looper
.
- Каждый
Looper
имеет связанный MessageQueue
- Обработчик использует нижнюю часть
Looper
для постановки в очередь и удаления сообщений потокобезопасным способом в Looper
'MessageQueue
.
- Объекты-обработчики по своей природе поточно-ориентированы и, следовательно, могут безопасно передаваться другим потокам.
- Вы можете иметь несколько
Handler
объектов, привязанных к одному и тому же Looper
. Это полезно, если вы хотите обрабатывать разные виды сообщений, используя разные обработчики. В этом случае вам гарантируется, что только один из обработчиков обработает сообщение / Runnable для данного Looper
. Looper
отвечает за отправку сообщения вправо Handler
.
- Если вы уже знакомы с парадигмой очереди сообщений для связи между двумя потоками (или схожим шаблоном буферизованного канала
golang
), Handler
- это просто класс высокого уровня, который позволяет легко использовать этот шаблон.
Пример использования обработчика для отправки / получения сообщений, публикация Runnables
// BEGIN One-time Initialization
// Create a Handler thread
// This provides the looper for the Message Queue and
// will be processing all your messages (i.e. tasks).
handlerThread = new HandlerThread("SomeThreadName");
// Start the Handler Thread
// The thread will block (using the looper) until it
// receives a new message
handlerThread.start();
// Create a Message Handler which you can use to
// post and process messages
// The same Handler can also be used to post a Runnable which will get
// executed on handlerThread
handler = new CustomHandler(mHandlerThread.getLooper());
// END One-time Initialization
// Different ways to post a message to the Handler Thread
// These calls are thread-safe, can be called safely and
// concurrently from multiple threads without race conditions
handler.sendEmptyMessage(MESSAGE_ID_1);
handler.sendEmptyMessage(MESSAGE_ID_2);
handler.sendMessage(handler.obtainMessage(MESSAGE_ID_3, obj1));
handler.sendMessage(handler.obtainMessage(MESSAGE_ID_4, value, obj1));
handler.sendMessage(handler.obtainMessage(MESSAGE_ID_5, value1, valu2, obj1));
// Post a runnable on the Handler Thread
// This is thread-safe as well
// In fact all methods on the Handler class are thread-safe
handler.post(new Runnable() {
@Override
public void run() {
// Code to run on the Handler thread
}
});
// A skeleton implementation for CustomHandler
// NOTE: You can use the Handler class as-is without sub-classing it, if you
// intend to post just Runnables and NOT any messages
public class CustomHandler extends Handler {
public CustomHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message message) {
if (message != null) {
// Process the message
// The result can be sent back to the caller using a callback
// or alternatively, the caller could have passed a Handler
// argument, which the Handler Thread can post a message to
switch (message.what) {
case MESSAGE_ID_1:
// Some logic here
break;
case MESSAGE_ID_2:
// Some logic here
break;
case MESSAGE_ID_3:
// Some logic here
break;
case MESSAGE_ID_4:
// Some logic here
break;
case MESSAGE_ID_5:
// Some logic here
break;
// Add more message types here as required
}
}
}
}
// After you're done processing all messages and you
// want to exit the Handler Thread
// This will ensure that the queue does not accept any
// new messages, and all enqueued messages do get processed
handlerThread.quitSafely();
Отклонения от приведенного выше примера
- Хотя я использовал
HandlerThread
в приведенном выше примере, его использование не обязательно. Вы даже можете напрямую использовать вызовы Looper
, то есть Looper.prepare()
и Looper.loop()
, чтобы запустить свой собственный цикл сообщений в потоке.
- Как уже упоминалось в комментариях, вам не нужно подразделять акции
Handler
, если вы не собираетесь обрабатывать какие-либо сообщения.
- Вы можете легко общаться между несколькими потоками, используя
Handler
для каждого потока, которому необходимо получить сообщение.
- В
Handler
есть методы для планирования доставки сообщений и выполнения в будущем.
Платформа Android внутренне использует Handler
для управления событиями жизненного цикла компонентов (onPause
, onResume
и т. Д.).
AsyncTask
AsyncTask - еще одна альтернатива планированию задач в другом потоке. , Я не буду вдаваться в подробности его реализации, поскольку документация для разработчиков Android уже описывает его подробно.
Я обычно использую AsyncTasks для задач, которые, как я знаю, будут использовать фоновый поток в течение длительного времени (легко> = 100 мс как минимум). Вот некоторые примеры, относящиеся к этой категории: Binder IPC, RPC-вызовы, сетевые вызовы, фоновые загрузки и т. Д.
С другой стороны, Handler
более приспособлен для ситуаций, сосредоточенных на обработке большего количества сообщений как можно быстрее. Другими словами, избегайте выполнения какой-либо операции блокировки в handleMessage()
. Вы можете легко написать код без блокировки, используя Handler
, он управляет всеми блокировками за вас при постановке в очередь и снятии с очереди сообщений.
Фактически AsyncTask
можно использовать в комбинации с Handler
, разбивая работу на быструю часть (заботится Handler
) и медленную часть (заботится AsyncTask
).
PS: Хотя это и касается вопроса, если вас интересует парадигма очереди сообщений; взгляните на LMAX Disruptor
, высокопроизводительную библиотеку очереди сообщений между потоками. Их проектный документ довольно хорошо объясняет, какие части очереди сообщений нуждаются в блокировке / атомарном доступе.