Android上有任务队列这样的东西吗?我知道它可以手工编写,但是有一个可以使用的库吗?
答案 0 :(得分:9)
我不确定是否会有这个库,因为Android已经为你想要实现的目标提供了高级构建块。
如果我理解正确,您希望从任何线程发布任务,以便在专用线程上逐行排队并执行。这就是Android Handler
的用途。
Looper
绑定。Looper
都有一个关联的MessageQueue
Looper
以线程安全的方式将邮件排入队列并将其出列到Looper
的{{1}}。MessageQueue
个对象绑定到同一个Handler
。如果要使用不同的处理程序处理不同类型的消息,这非常有用。在这种情况下,您可以保证只有一个处理程序将处理给定Looper
的Message / Runnable。 Looper
负责将消息发送到右侧Looper
。Handler
的缓冲通道模式)之间进行通信,那么golang
只是一个高级类,可以让您使用它模式很容易。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();
,但并不是必须使用它。您甚至可以直接使用HandlerThread
来电,即Looper
和Looper.prepare()
在线程中运行您自己的消息循环。Looper.loop()
进行子类化。Handler
轻松地在多个线程之间进行通信。Handler
中有一些方法可以在将来安排邮件传递和Runnable执行。 Android的框架内部广泛使用Handler
来管理组件生命周期事件(Handler
,onPause
等。)。
AsyncTask是在不同线程上调度任务的另一种选择。 。我不会详细介绍其实现,因为Android开发人员文档已经详细描述了它。
我通常使用AsyncTasks来完成我知道我将长时间使用后台线程的任务(至少很容易> = 100 ms)。我可以想到的一些属于这个类别的例子是Binder IPC,RPC调用,网络调用,后台下载等。
另一方面,onResume
更适合于尽可能快地处理更多数量的消息的情况。换句话说,避免在Handler
中执行任何阻止操作。您可以使用handleMessage()
轻松编写无锁代码,它可以在排队和出列消息时为您管理所有锁定。
事实上,Handler
可以与AsyncTask
结合使用,将工作分成快速部分(由Handler
处理)和缓慢部分(由{{1照顾) }})。
PS:虽然你对问题很感兴趣,但是如果你对Message Queue范例感兴趣的话。请查看LMAX Disruptor
,它是一个高性能的线程间消息队列库。他们的设计文档很好地解释了Message Queue的哪些部分需要锁定/原子访问。
答案 1 :(得分:3)
我不知道iOS所以我不确定它是否相同,但在Android中你有ScheduledThreadPoolExecutor
答案 2 :(得分:3)
我也在寻找像GCD for Android这样的东西。虽然处理程序和AsyncTasks非常棒,但GCD(我的拙见)的优点在于您可以在后台线程上调度工作负载来完成繁重的任务。执行完成后,我可以轻松地在UI线程上执行UI更新。
由于我没有找到任何东西,我的学校伙伴决定创建我们自己的一个。 您可以在以下位置找到它: ICDispatch on github
基本上你需要做的就是声明一个扩展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.
}
}
}
});
最糟糕的是,会有很多缩进。为了尽量减少缩进,您可以使用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排队。功能将在实施时添加。
答案 3 :(得分:1)
对于现在找到此主题的任何人,都有一个名为Bolts的新框架。它有任务和延续,可以等待多个任务完成,如GCD。
答案 4 :(得分:1)
我从Telegram Code中获取此样本:
您可以为此方法声明扩展线程
public static volatile DispatchQueue globalQueue = new DispatchQueue("globalQueue");
班级是:
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 */
}
});
答案 5 :(得分:0)
你应该检查Handler&amp;弯针
处理程序,默认情况下(*),如dispatch_get_main_queue(),您可以发布任何代码块(Runnable实例)。使用Context.runOnUiThread()和View.post(Runnable)也可以获得相同的方法
(*)Handler的默认构造函数继承当前线程的Looper实例(iOS中的RunLoop)和队列(通过handlerInstace.post ...()方法)Looper上的Runnable实例。
更多提前使用。您可以创建自己的Looper实例(请注意它有点棘手:))。这仍然可能很方便......
另外,对于更高级的使用,处理程序是我在Android上遇到的最好的工具(是的,我想念它们在iOS上),用于在应用程序内部进行消息传递(我猜是进程间通信)。他们可能会被定制来处理发布的消息,bla,bla ......