我有一个事件在服务中发现的runnable中触发。
主要的runnable由TimerTask
启动。此主runnable中的事件应该依次生成worker threads
。
threads
应该按照它们产生的顺序工作并完成。
在Android中执行此操作的最佳方式是什么?
我看过AsyncTasks
,Exexcutor
,ThreadPool
等信息,但我不知道什么是最佳做法。
我只需要一些处理此问题的方法的简短示例。
服务类看起来像这样:
public onCreate(){
runnable = new Runnable() {
public void run(){
object.addListener(new Listener() {
public void onEvent(Event event) {
// Put Code here to spawn sequential worker threads ...
}
}
}
}
我在方法和成员方面添加了什么以及onEvent中的内容?谢谢!
答案 0 :(得分:3)
由于您谈论服务,我假设您的任务不必直接与用户界面交互。您可以使用ThreadPoolExecutor,它实现Executor接口。此代码片段将创建一个只包含一个线程的线程池,这意味着所有Runnable实例将按顺序执行。由于这只会为您的任务创建一个Executor,因此该方法不会阻止执行任何其他任务。
Executor tpe = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
tpe.execute(new Runnable() {
@Override
public void run() {
// Do your runnable task
}
});
Executor将是您服务的成员变量,执行部分应该在您的onEvent方法中。
但是,如果您需要与用户界面进行交互,那么您可以使用AsyncTask来解决使用UI线程同步调用的问题。 AsyncTask需要在UI线程上创建,因此在您的情况下,这只有在UI线程触发onEvent时才有效。另请注意,您的Runnables将在您的活动可能使用的任何其他AsyncTask之间执行。因此,如果您在服务中泛洪AsyncTask队列,那么您最终可能会遇到似乎没有运行的任务,因为它们可能在队列中很长时间。另请注意,在Android版本的历史记录中,执行AsyncTasks的方式已更改:
首次引入时,AsyncTasks在单个上串行执行 背景线程。从DONUT开始,这被改成了一个池 允许多个任务并行运行的线程。从...开始 HONEYCOMB,任务在单个线程上执行以避免常见 并行执行导致的应用程序错误。 Source
从API级别11开始,您还可以使用executeOnExecutor在我们创建的ThreadPoolExecutor上执行AsyncTask。
Executor tpe = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
AsyncTask asyncTask = new AsyncTask() {
@Override
protected Object doInBackground(Object[] objects) {
return null;
}
};
asyncTask.executeOnExecutor(tpe, params);
这段代码演示了序列化的执行行为。创建一次ThreadPoolExecutor,然后for循环将向ThreadPoolExecutor队列添加5个任务。 Runnable无名类将在任务开始时向控制台输出一条消息,然后它将在它结束之前至少休眠两秒,并显示刚刚结束的消息。
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) {
// Our thread pool consists of 1 thread
final Executor tpe = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
for (int i=0; i<5; i++) {
final int index = i;
tpe.execute(new Runnable() {
@Override
public void run() {
System.out.println("Running task: " + index);
try {
// Sleeping at least 2 seconds to pretend to be doing something CPU intensive
Thread.sleep(2000);
} catch (InterruptedException e) {
// lets ignore this for simplicity
}
System.out.println("Finished task: " + index);
}
});
}
}
}
结果输出为:
Running task: 0
Finished task: 0
Running task: 1
Finished task: 1
Running task: 2
Finished task: 2
Running task: 3
Finished task: 3
Running task: 4
Finished task: 4
如果我们为了演示目的,通过用这段代码替换tpe变量初始化,为ThreadPool添加了一个额外的Thread:
final Executor tpe = new ThreadPoolExecutor(2, 2, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
然后输出将指示它同时运行多个任务。
Running task: 0
Running task: 1
Finished task: 1
Finished task: 0
Running task: 2
Running task: 3
Finished task: 2
Finished task: 3
Running task: 4
Finished task: 4