Android中的线程模型-ThreadPoolExecutor (十二)

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提交到线程池去执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值