Android上的任务队列就像iOS上的GCD一样?

Kos*_*sky 20 multithreading android grand-central-dispatch ios

在Android上有任务队列吗?我知道它可以手工编写但是有一个可以使用的库吗?

Tux*_*ude 9

我不确定是否会有这个库,因为Android已经为你想要实现的目标提供了高级构建块.

处理器

如果我理解正确,您希望从任何线程发布任务,以便在专用线程上逐个排队并执行.这非常适合Android Handler.

Handler,Looper和MessageQueue的关键特性

  • 处理程序与单个绑定Looper.
  • 每个Looper都有一个相关的MessageQueue
  • 处理器采用的是Looper下入队和出队在一个线程安全的方式邮件到LooperMessageQueue.
  • 处理程序对象本质上是线程安全的,因此可以安全地传递给其他线程.
  • 您可以将多个Handler对象绑定到同一个对象Looper.如果要使用不同的处理程序处理不同类型的消息,这非常有用.在这种情况下,您可以保证只有一个处理程序将处理给定的Message/Runnable Looper.在Looper需要调度消息,以正确的护理Handler.
  • 如果您已经熟悉Message Queue范例,可以在2个线程(或类似golang的缓冲通道模式)之间进行通信,那么Handler它只是一个高级类,可以让您轻松使用此模式.

Runnables发布后使用Handler发送/接收消息的示例

// 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();
Run Code Online (Sandbox Code Playgroud)

偏离上面的例子

  • 虽然我HandlerThread在上面的例子中使用过,但并不是必须使用它.你甚至可以使用Looper直接通话,也就是Looper.prepare()Looper.loop()运行在一个线程自己消息循环.
  • 正如评论中已经提到的,Handler如果您不打算处理任何消息,则无需对库存进行子类化.
  • 通过Handler对每个需要接收消息的线程使用a ,您可以轻松地在多个线程之间进行通信.
  • 还有一些方法可以在Handler将来安排消息传递和Runnable执行.

Android的框架内部使用Handler大量用于管理组件生命周期事件(onPause,onResume,等).

的AsyncTask

AsyncTask是在不同线程上调度任务的另一种替代方法..我不会详细介绍其实现,因为Android开发人员文档已经详细描述了它.

我通常使用AsyncTasks来完成我知道我将长时间使用后台线程的任务(至少容易> = 100 ms).我可以想到的一些属于这个类别的例子是Binder IPC,RPC调用,网络调用,后台下载等.

另一方面,Handler更适合于尽可能快地处理更多数量的消息的情况.换句话说,避免执行任何阻塞操作handleMessage().您可以轻松编写无锁代码Handler,它可以在排队和出列消息时为您管理所有锁定.

实际上AsyncTask可以Handler通过将工作分成快速部分(照顾Handler)和慢速部分(照顾AsyncTask)来结合使用.

PS:虽然你对问题很感兴趣,但是如果你对Message Queue范例感兴趣的话.请看一下LMAX Disruptor,这是一个高性能的线程间消息队列库.他们的设计文档很好地解释了Message Queue的哪些部分需要锁定/原子访问.


THe*_*per 3

我不了解 iOS,所以我不确定它是否相同,但在 Android 中你有ScheduledThreadPoolExecutor