手动实现多任务调度控制器

        我们知道CPU处理多线程时是利用线程调度来实现的,线程调度主要依据线程的组别(是否前台)和优先级来进行,我们可以利用一个线程来模拟CPU的单核行为,对多任务进行调度。

       在任务执行过程中可能发生各种各样的状态和阶段,可以利用监听者模式,来通知监听者任务的调度状态。


  1. 4)任务调度主线程:

    首先定义一个监听器类,用于线程执行状态的反馈;
public class MyListener {

	public void downloadAppStarted(){};
	
	public void downloadAppFinished(){};
	

}

  1. 实现主控制器,首先该控制器必须为单例,其次其为一个线程,不断的循环处理任务,可执行任务封装为Command,且其必须实现Comparable接口,用以对不同优先级的任务进行调度。

1)任务封装:

	/**
	 * 消息队列中的命令封装
	 * 命令调度:1比较是否为isForeGround线程 2比较sequence 大小,越大优先级越高 
	 * @author 
	 *
	 */
	static class Command implements Comparable<Command> {

		public Runnable runnable;
		public MyListener mListener;
		public String description;
		boolean isForeGround;		//是否为前台进程
		
		int sequence ;
		@Override
		public int compareTo(Command another) {
			// TODO Auto-generated method stub
			if (another.isForeGround && !isForeGround) {
				return 1;
			} else if(!another.isForeGround && isForeGround) {
				return -1;
			} else {
				return sequence - another.sequence;
			}
		}
		
	}

2)主控制器类:

	public class MyController implements Runnable {
		private Thread mThread; //当前主线程类的执行线程
		private BlockingQueue<Command> mCommands = new PriorityBlockingQueue<MyController.Command>();
		private boolean mBusy = false; //标识当前线程的运行状态;
		private static AtomicInteger sequencing = new AtomicInteger(0); //线程安全的整数,用来定义线程优先级,
		//记录监听接口,口需要通知接口时,遍历所有接口,进行通知
		private Set<MyListener> mListeners = new CopyOnWriteArraySet<MyListener>();
		private Application mApplication;
	
	
		private static MyController inst = null;
		
		/** 方法前加synchronized 与方法内部使用双重检查有什么区别
		 * 单例工厂类方法
		 * @return
		 */
		public synchronized static MyController getInstance(Application application) {
			if(inst == null) {
				inst = new MyController(application);
			}
			return inst;
		}
		
		(3)构造方法为private ,且在构造方法中开启自己的主线程
		/**
		 * 构造方法
		 * @param application
		 */
		private MyController(Application application) {
			mApplication = application;
			mThread = new Thread(this);//线程使用runnable对象初始化
			mThread.setName("MyController");
			mThread.start();
		}


(3)构造方法为private ,且在构造方法中开启自己的主线程

		/**
		 * 构造方法
		 * @param application
		 */
		private MyController(Application application) {
			mApplication = application;
			mThread = new Thread(this);//线程使用runnable对象初始化
			mThread.setName("MyController");
			mThread.start();
		}


4)任务调度主线程:


		@Override
		public void run() {
			// TODO Auto-generated method stub
			Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
			while(true) {
				String commanDescription = null;
				try {
					final Command command = mCommands.take();
					
					if(command != null) {
						commanDescription = command.description;
						mBusy = true;
						
						//任务执行成功,消息通知
						for (MyListener l : getListeners(command.mListener)) {
							l.downloadAppStarted();
						}
						try {
							command.runnable.run();
						} catch(Exception e){
							//如果执行过程中出错,则重新过30s重新把任务放入队列
							new Thread() {
	
								@Override
								public void run() {
									// TODO Auto-generated method stub
									try {
										sleep(30 * 1000);
										mCommands.put(command);
									} catch (InterruptedException e){
										e.printStackTrace();
									}
								}
								
							}.start();
						}
					}
					
					//任务执行成功,消息通知
					for (MyListener l : getListeners(command.mListener)) {
						l.downloadAppFinished();
					}
				} catch(Exception e) {
	//				e.printStackTrace();
					Log.e("TAGD", "Error running command '" + commanDescription + "'", e);
				}
				mBusy = false;
			}
		}

5)任务添加

		/**
		 * 任务队列任务管理,任务添加
		 * 每次添加任务,如果失败,重复添加5次,如果仍然失败可以抛出错误
		 */
		private void putCommand(BlockingQueue<Command> queue, String description, MyListener listener, Runnable runnable, boolean isForeGround) {
			int retries = 5;
			Exception e = null;
			while(retries-- > 0) {
				try {
					Command command = new Command();
					command.mListener = listener;
					command.description = description;
					command.isForeGround = isForeGround;
					command.runnable = runnable;
					queue.put(command);
					return ;
				} catch (InterruptedException ie) {
					
					try {
						Thread.sleep(200);
					} catch (InterruptedException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					e = ie;
				}
			}
			throw new Error(e);
		}
		
		/**
		 * 默认添加到后台
		 * @param description
		 * @param listener
		 * @param runnable
		 */
		private void putBackground(String description, MyListener listener, Runnable runnable) {
			putCommand(mCommands, description, listener, runnable, false);
		}
		
		/**
		 * 默认添加到前台组
		 * @param description
		 * @param listener
		 * @param runnable
		 */
		private void putForground(String description, MyListener listener, Runnable runnable) {
			putCommand(mCommands, description, listener, runnable, true);
		}

6 )监听器控制:
		/**
		 * 监听通知
		 */
		public void addListener(MyListener listener) {
			mListeners.add(listener);
		}
		
		public void removeListener(MyListener listener) {
			mListeners.remove(listener);
		}
		
		public Set<MyListener> getListeners(MyListener listener) {
			if(listener == null) {
				return mListeners;
			}
			
			Set<MyListener> listeners = new HashSet<MyListener>(mListeners);
			listeners.add(listener);
			return listeners;
		}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值