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

Android上的任务队列有这样的事情吗? 我知道它可以用手写,但是有没有准备好使用的库?

Solutions Collecting From Web of "Android上的任务队列就像iOS中的GCD一样?"

我不确定是否会有这样一个库,因为Android已经提供了您要实现的高级构build块。

处理器

如果我正确地理解了你,你想要从任何线程发布任务,在一个专用的线程上逐一排队和执行。 这是Android Handler的意义所在。

Handler,Looper和MessageQueue的关键特性

  • 处理程序绑定到一个单一的Looper
  • 每个Looper都有一个关联的MessageQueue
  • Handler使用下面的Looper以线程安全的方式将消息入队和出队到LooperMessageQueue
  • 处理程序对象本质上是线程安全的,因此可以安全地传递给其他线程。
  • 您可以将多个Handler对象绑定到同一个Looper 。 如果要使用不同的处理程序处理不同种类的消息,这非常有用。 在这种情况下,我们保证只有其中一个处理程序将为给定的Looper处理消息/ Runnable。 Looper负责将消息发送给右侧的Handler
  • 如果您已经熟悉2线程(或类似的golang的缓冲通道模式)之间的消息队列范例, Handler只是一个高级的类,可以让您轻松使用这个模式。

使用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 (ie 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还有一些方法可以在将来计划消息传递和Runnable执行。

Android的框架内部广泛使用Handler来pipe理组件生命周期事件( onPauseonResume等)。

的AsyncTask

AsyncTask是在另一个线程上调度任务的另一种方法。 。 我不会详细介绍它的实现,因为Android开发者文档已经详细描述了它。

我通常使用AsyncTasks来执行任务,我知道我将使用后台线程很长一段时间(至less轻松> 100 ms)。 属于这个类别的一些例子我能想到的是Binder IPC,RPC调用,networking调用,后台下载等等。

另一方面, Handler更适合专注于尽快处理更多消息的情况。 换句话说,不要在handleMessage()执行任何阻塞操作。 您可以使用Handler轻松编写无锁代码,在排队和出队消息时pipe理所有locking。

事实上, AsyncTask可以和Handler结合使用,将工作分解成一个快速部分(由Handler )和一个慢部分(由AsyncTask )。

PS:尽pipe问题相关,但如果您对Message Queue范例感兴趣, 请查看LMAX Disruptor ,这是一个高性能的线程间消息队列库。 他们的devise文档很好地解释了Message Queue的哪些部分需要locking/primefaces访问。

我不知道的iOS,所以我不知道是否相同,但在Android中,你有ScheduledThreadPoolExecutor

我也看了一些像Android的GCD的东西。 虽然Handlers和AsyncTasks非常棒,但GCD的美妙之处在于你可以派遣一个工作负载在后台线程来完成繁重的工作。 当执行完成后,我很容易在UI线程上执行UI更新。

由于我没有find任何东西,我的同学决定创build一个我们自己的。 你可以在github的ICDispatch上find它

基本上所有你需要做的就是声明一个扩展ICDispatchApplication而不是Application的Application类,并且当你想发送你刚刚调用的东西

App.executeOn(int queue, ICBlock block);

例:

 App.executeOn(ICDispatch.NORMAL, new ICBlock(){ public void run(){ //do stuff... App.executeOn(ICDispatch.MAIN, new ICBlock(){ public void run(){ //post result to UI thread. } } } }); 

最糟糕的是会有很多缩进。 为了减less缩进,你可以使用lambda表示法:

 App.executeOn(ICDispatch.NORMAL, ()->{ //do stuff... //do some more... //then even more App.executeOn(ICDispatch.MAIN,() -> { //Post result on UI thread. } }); 

目前ICDispatch支持LOW,NORMAL,HIGH,MAIN和CONCURRENT排队。 function将在实施时添加。

现在任何人find这个线程,有一个新的框架可用称为螺栓 。 它有任务和延续,可以等待多个任务完成,比如GCD。

我从这个电报代码中抽取这个样本:

您可以为此方法声明扩展线程

 public static volatile DispatchQueue globalQueue = new DispatchQueue("globalQueue"); 

这个class是:

 import android.os.Handler; import android.os.Looper; import android.os.Message; import java.util.concurrent.CountDownLatch; public class DispatchQueue extends Thread { private volatile Handler handler = null; private CountDownLatch syncLatch = new CountDownLatch(1); public DispatchQueue(final String threadName) { setName(threadName); start(); } private void sendMessage(Message msg, int delay) { try { syncLatch.await(); if (delay <= 0) { handler.sendMessage(msg); } else { handler.sendMessageDelayed(msg, delay); } } catch (Exception e) { FileLog.e("tmessages", e); } } public void cancelRunnable(Runnable runnable) { try { syncLatch.await(); handler.removeCallbacks(runnable); } catch (Exception e) { FileLog.e("tmessages", e); } } public void postRunnable(Runnable runnable) { postRunnable(runnable, 0); } public void postRunnable(Runnable runnable, long delay) { try { syncLatch.await(); if (delay <= 0) { handler.post(runnable); } else { handler.postDelayed(runnable, delay); } } catch (Exception e) { FileLog.e("tmessages", e); } } public void cleanupQueue() { try { syncLatch.await(); handler.removeCallbacksAndMessages(null); } catch (Exception e) { FileLog.e("tmessages", e); } } @Override public void run() { Looper.prepare(); handler = new Handler(); syncLatch.countDown(); Looper.loop(); } } 

和来电者:

 globalQueue.postRunnable(new Runnable() { @Override public void run() { /* do here what you want */ } }); 

你应该检查处理程序和循环

处理程序,默认情况下(*),像dispatch_get_main_queue(),你可以发布任何代码块(Runnable实例)。 同样的方法也通过Context.runOnUiThread()和View.post(Runnable)

(*)Handler的默认构造函数inheritance当前线程的Looper实例(iOS中的RunLoop)和队列(通过handlerInstace.post …()方法)Looper上的可运行实例。

提前使用。 你可以创build自己的Looper实例(注意它有点棘手:))。 不过这可能是方便的…

同样为了更高级的用法,处理程序是我在Android上遇到的最好的工具(是的,我错过了它们在iOS上)用于在应用程序内进行消息传递(我猜是进程间通信)。 他们可能会被定制为处理张贴的消息,bla,bla …