Android中的并行编程方式:
1),上一篇 Android的线程模型:Android线程模型介绍了 Android中使用线程跟java中没有太多区别,只要继承Thread类或者实现Runnable接口就可以,只是这种实现方式要跟主线程通信需要通过message queue;
2),另一种并行编程方法是AsyncTask,这是Android开发的专门简化多线程实现的类,可以不用繁琐的looper,handler等机制就可以与主线程通信,但是AsyncTask的设计目标是针对较短时间的后台操作,如果需要在后台长时间的执行某项任务,还是使用并发包中的api,如java.util.concurrent包中的Executor,ThreadPoolExecutor,featureTask等。
3)IntentService,只需要实现onHandleIntent接口,就可以用非常简洁的语句对service进行后台处理,它会起一个后台线程处理请求,完成工作后自动停止(stop service)。
下面的demo,展示了如何在项目中使用线程池,在项目中通常不止一类task要提交到线程池运行,所以这里使用了泛型,没有加什么注释,因为相关的api中都有介绍。
1,ThreadPool是项目中线程池的封装类,需要使用线程池的地方,可以获取ThreadPool实例,然后submit任务到线程池执行。
public class ThreadPool {
private static final int CORE_POOL_SIZE = 4; //
private static final int MAX_POOL_SIZE = 8;
private static final int KEEP_ALIVE_TIME =10;//10 seconds
private Executor mExecutor;
//类似于Callable,但是他有一个参数JobContext
protected interface Job<T> {
public T run(JobContext jc);
}
//这个接口可以定义一些跟上下文有关的信息。
protected interface JobContext {
}
public ThreadPool(){
this(CORE_POOL_SIZE,MAX_POOL_SIZE);
}
public ThreadPool(int initPoolSize, int maxPoolSize){
mExecutor = new ThreadPoolExecutor(initPoolSize,maxPoolSize,KEEP_ALIVE_TIME,TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(1),
new PriorityThreadFactory("thread-pool",10));
}
public <T> FeatureExt<T> submit(Job<T> job, FeatureExtListener<T> listener){
Worker<T> worker = new Worker<T>(job, listener);
mExecutor.execute(worker);
return worker;
}
private class Worker<T> implements Runnable, FeatureExt<T>, JobContext{
private Job<T> mJob;
private FeatureExtListener<T> mListener;
private T result;
public Worker(Job<T> job, FeatureExtListener<T> listener){
mJob = job;
mListener = listener;
}
@Override
public void run() {
result = mJob.run(this);
if(mListener != null){
mListener.featureDone(this);
}
System.out.println("Worker="+Thread.currentThread().getName());
}
@Override
public T get() {
return result;
}
}
}
2,PriorityThreadFactory是ThreadFactory的继承类,当然也可以在ThreadPool中使用默认的factory,这里自定义类的目的是方便设置线程的名字,还是就是Android中通常需要设置线程的优先级,比如可以设置它是一个后台线程:THREAD_PRIORITY_BACKGROUND
public class PriorityThreadFactory implements ThreadFactory {
private final AtomicInteger mNumber = new AtomicInteger();
private final String mName;
private final int mPriority;
//在android中,可以设置线程的优先级。
public PriorityThreadFactory(String name,int priority){
mName = name;
mPriority = priority;
}
@Override
public Thread newThread(Runnable r) {
return new Thread(r,mName+":"+mNumber.getAndIncrement()){
@Override
public void run() {
//在android中,可以设置线程的优先级。
//Process.setThreadPriority(mPriority);
super.run();
}
};
}
}
3,FeatureExt,类似于java并发包中的Feature,自定义后,可以添加扩展一些项目中特定的功能,比如cancel执行等。
//FeatureExt可以用java.util.concurrent.Future
public interface FeatureExt<T> {
public T get();
}
4,这是一个跟FeatureExt配合的监听类,可以在Feature执行过程中,或者执行完成时,执行相应的动作,跟FeatureExt一样都是接口,需要在定义具体任务时提供实现类。
public interface FeatureExtListener<T> {
public void featureDone(FeatureExt<T> feature);
}
5,下面是一个测试demo,其中每一个具体的任务的定义都是实现了ThreadPool的内部类Job,
public class RunTest {
private static ThreadPool mThreadPool;
@SuppressWarnings("unchecked")
public static void main(String[] args) {
mThreadPool = new ThreadPool();
mThreadPool.submit(new SubJob(), new SubListener());
}
private static class SubListener implements FeatureExtListener<StringBuffer>{
@Override
public void featureDone(FeatureExt<StringBuffer> feature) {
StringBuffer str = feature.get();
System.out.println("Run end:"+str);
}
}
private static class SubJob implements ThreadPool.Job<StringBuffer>{
@Override
public StringBuffer run(ThreadPool.JobContext jc) {
StringBuffer str = new StringBuffer("begin:");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("SubJob="+Thread.currentThread().getName());
Long time = System.currentTimeMillis();
str.append(str+"-"+time);
return str;
}
}
}
运行结果:
SubJob=thread-pool:0
Run end:begin:begin:-1520559010001
Worker=thread-pool:0
可以在项目中不同的地方,通过mThreadPool.submit(new SubJob(), new SubListener());提交多个自定义的job。
比如说在gallery中需要处理image,video,gif资源的解码,就是分别定义了相应的job提交到线程池去执行。