多线程处理

来源:互联网 发布:淘宝旺铺模板页头 编辑:程序博客网 时间:2024/04/29 05:20
package com.fcar.frameworks.tasks;/** * 用于处理通讯收发的线程类。(这个注释似乎已经不能很好的描述其实际用途了,大概“执行一般性一次性后台任务的线程类更贴切”)<br/> * 同一时间一次只有一个对象可以运行 */public class CommThread extends Thread {   /** 额外参数 */   private Object mParam;   /** 要执行的任务 */   private ITask mTask;   /**    * 实现临界区的信号量    */   private static int times = 0;   /**    * 构造函数    * @param t 任务    * @param param 额外参数    */   public CommThread(ITask t, Object param) {      mParam = param;      mTask = t;      super.start();   }   /**    * 什么都不做,因为在构造器中已经启动线程,这里覆盖父类方法只是为了防止创建对象后又调用一次start方法    */   @Override   public void start() {   }   /**    * 用于同步访问times变量    */   private static final Object lock = new Object();   /**    * 进入临界区,一次只允许一个CommThread或者{@link TaskManager#addLoopTask_(int, ITask, Object) 循环任务压栈任务}进入临界区    */   public static void enterCriticalArea() {      while (true) {         synchronized (lock) {            if (times == 0) {               times = 1;               break;            }         }         TaskManager.Sleep(10);      }   }   /**    * 退出临界区,只有退出临界区以后别的CommThread或者{@link TaskManager#addLoopTask_(int, ITask, Object) 循环任务压栈任务}才可以进入临界区。    * 如果你有程序进入临界区,一定要保证它一定会退出临界区    */   public static void exitCriticalArea()  {      synchronized (lock) {         times = 0;      }   }   @Override   public void run() {      if (mTask == null)         return;      enterCriticalArea();      // 写成try语句保证退出临界区执行      try {         TaskManager.loopTaskPause();         mTask.doWork(mParam);         TaskManager.loopTaskResume();      } finally {         exitCriticalArea();      }   }

}

package com.fcar.frameworks.tasks;/** * 任务接口, 任何需要进行的工作都可以认为是一个Task */public interface ITask {   boolean doWork(Object param);}

package com.fcar.frameworks.tasks;import java.util.ArrayList;import java.util.Calendar;import java.util.List;/** * 多重循环的任务, 多个循环任务同时循环 */public class MutiTasks implements ITask {   /**    * 任务列表    */   List<TaskObj> taskList;   /**    * 多重任务中每个任务的详细信息    */   public class TaskObj {      /**       * 任务过程       */      ITask task;      /**       * 额外参数       */      Object param;      /**       * 循环时间间隔       */      int loopTimes;      /**       * 优先级,数值越小优先级越高       */      int prio;      /**       * 下次可运行的时间,动态计算       */      long nexttime;      public TaskObj(int _loopTimes, int _prio, ITask _task, Object _param) {         loopTimes = _loopTimes;         prio = _prio;         task = _task;         param = _param;         setNextTime();      }      public void setNextTime() {         nexttime = Calendar.getInstance().getTimeInMillis() + loopTimes;      }      public boolean isTimeTorun() {         return nexttime <= Calendar.getInstance().getTimeInMillis();      }   }   /**    * 构造器    */   public MutiTasks() {      taskList = new ArrayList<TaskObj>();   }   /**    * 增加一个循环任务    * @param loopTimes 循环时间间隔    * @param prio 优先级别, 数字越小优先级别越高    * @param task 任务过程    * @param param 额外参数    */   public void addTask(int loopTimes, int prio, ITask task, Object param) {      if (task == null) return;      taskList.add(new TaskObj(loopTimes, prio, task, param));   }   /**    * 删除一个循环任务    * @param task 指定任务的引用    */   public void delTask(ITask task) {      for (TaskObj o : taskList) {         if (o.task == task) {            taskList.remove(o);            return;         }      }   }   /**    * 执行任务。任务列表中找到可执行的优先级最高的任务执行    * @param param 额外参数,目前没有任何用处    * @return 没有要执行的任务返回false,否则返回true    */   @Override   public boolean doWork(Object param) {      TaskObj res = null;      for (TaskObj o : taskList) {         if (o.isTimeTorun()) {            if (res == null)               res = o;            else if (res.prio > o.prio)               res = o;         }      }      if (res == null) return false;      res.setNextTime();      res.task.doWork(res.param);      return true;   }}

package com.fcar.frameworks.tasks;import android.os.Looper;import com.fcar.frameworks.utils.L;import java.util.Calendar;import java.util.List;import java.util.Stack;import java.util.Vector;/** * 任务管理器 */public class TaskManager {   private TaskManager() {   }   /**    * 任务的运行状态:正在运行,暂停,销毁    */   enum Cmd {      CMD_RUN, CMD_PAUSE, CMD_DELETE   }   /**    * 任务参数    */   static class Param {      /**       * 任务过程       */      ITask mTask;      /**       * 任务额外参数       */      Object mParam;      /**       * 任务当前状态       */      Cmd mCmd;      /**       * 任务前一个状态       */      Cmd mStatus;      /**       * 任务循环时间间隔       */      int loopTimes;      /**       * 任务下次执行的时间       */      long nexttime;      public Param(int _looptimes, ITask task, Object param) {         mTask = task;         mParam = param;         mCmd = Cmd.CMD_RUN;         mStatus = Cmd.CMD_RUN;         loopTimes = _looptimes;      }      /**       * 设置下次应该运行的时间戳       */      public void setNextTime() {         nexttime = Calendar.getInstance().getTimeInMillis() + loopTimes;      }      /**       * 判断是否到了该执行的时间       * @return       */      public boolean isTimeTorun() {         return nexttime <= Calendar.getInstance().getTimeInMillis();      }   }   /**    * 任务栈,循环任务(LoopTask)值执行该栈栈顶的任务.    */   // Stack是线程安全的   static Stack<Param> mStack = new Stack<Param>();   /**    * 执行循环任务的线程    */   static Thread mTLoop;   /**    * 辅助线程的任务列表,FIFO。主要用于向循环任务列表添加删除任务。因为这个List会被多个线程同时访问,使用Vector线程同步.    * (Java似乎没有现成的线程同步的链表,所以暂时先用Vector吧)    */   static List<Param> mList = new Vector<Param>();   /**    * 将任务放入循环线程的辅助线程    */   static Thread tTTemp;   /**    * 任务线程中止的标志    */   static boolean isThreadEnd;   /**    * 辅助线程任务的模板    */   static class MyTask implements ITask {      private Param mParam;      public MyTask(Param param) {         mParam = param;      }      @Override      public boolean doWork(Object param) {         Param p = mParam;         TaskManager.addLoopTask_(p.loopTimes, p.mTask, p.mParam);         return false;      }   }   /**    * 执行一个一般任务(一次性任务), 不等完成立即返回,可以在GUI内执行    * @param task 要执行的任务    * @param param 额外参数    */   public static void doTask(ITask task, Object param) {      if (TaskManager.isInThread()) {         L.e("TaskManager", "doTask already in Thread");      }      new CommThread(task, param);   }   /**    * 添加一个循环任务到系统 并立即起作用    * @param looptimes 循环时间间隔    * @param task 循环任务的过程    * @param param 额外参数    */   public static void addLoopTask(int looptimes, ITask task, Object param) {      if (tTTemp == null) {         isThreadEnd = false;         tTTemp = new AuxiliaryThread();         tTTemp.start();      }      // 将参数传入一个列表,供辅助线程使用,由辅助线程将任务加进任务栈      //使用单独的线程执行,防止commthread的死锁      Param p = new Param(looptimes, task, param);      MyTask m = new MyTask(p);      mList.add(new Param(0, m, null));   }   /**    * 将循环任务放入循环任务栈栈顶    * @param looptimes 循环任务的循环间隔时间,毫秒    * @param task 循环任务循环的内容    * @param param 额外参数    */   private static void addLoopTask_(int looptimes, ITask task, Object param) {      if (task == null) return;      if (mTLoop == null) {         mTLoop = new LoopTaskThread();         mTLoop.start();      }      // 避免在循环任务暂停期间(通常是因为要执行一次性任务)加入循环任务,从而导致循环任务和一次性任务同时运行      CommThread.enterCriticalArea();      // 用try,确保退出临界区      try {         loopTaskPause();         mStack.push(new Param(looptimes, task, param));         loopTaskResume();      } finally {         CommThread.exitCriticalArea();      }   }   /**    * 暂停循环任务,并等待循环任务真正暂停后返回。    * <font color="red">如果在UI中,则不会等待而是立即返回</font>    */   public static void loopTaskPause() {      if (mStack.size() == 0) return;      if (!isInThread()) {         mList.add(new Param(0, new ITask() {            @Override            public boolean doWork(Object param) {               loopTaskPause();               return false;            }         }, null));         return;      }      mStack.peek().mStatus = Cmd.CMD_RUN;      mStack.peek().mCmd = Cmd.CMD_PAUSE;      while (mStack.peek().mStatus != Cmd.CMD_PAUSE) {         TaskManager.Sleep(10);      }   }   /**    * 唤醒循环任务,并等待循环任务真正暂停后返回。    * <font color="red">如果在UI中,则不会等待而是立即返回</font>    */   public static void loopTaskResume() {      if (mStack.size() == 0) return;      if (!isInThread()) {         mList.add(new Param(0, new ITask() {            @Override            public boolean doWork(Object param) {               loopTaskResume();               return false;            }         }, null));         return;      }      mStack.peek().mStatus = Cmd.CMD_PAUSE;      mStack.peek().mCmd = Cmd.CMD_RUN;      while (mStack.peek().mStatus != Cmd.CMD_RUN) {         Sleep(10);      }   }   /**    * 当前线程休眠一段时间    * @param ms 休眠多少毫秒    */   public static void Sleep(int ms) {      try {         Thread.sleep(ms);      } catch (InterruptedException e) {         e.printStackTrace();      }   }   /**    * 判断当前线程是不是UI线程    * @return 如果不是UI线程,则返回true,否则返回false    */   public static boolean isInThread() {      return Looper.getMainLooper() != Looper.myLooper();   }   /**    * 撤销一个循环任务<br/>    * <p>细节是:循环任务退栈,并等待完全退栈,最后(如果存在)将新栈顶任务标记为运行后返回</p>    * <p><font color="red">注意,目前的实现中,你不可以在lookTask中调用该方法,这会造成死锁。</font></p>    */   public static void loopTaskBack() {      if (mStack.size() == 0) {         L.e("loopTaskBack", "Error:不可能的数据");         return;      }      if (!isInThread()) {         //L.w("退出发生在gui, loopTaskBack将立即返回,这可能会有风险,如果需要更长时间的退出动作,请new Thread来完成");         mList.add(new Param(0, new ITask() {            @Override            public boolean doWork(Object param) {               loopTaskBack();               return false;            }         }, null));         return;      }      Param p = mStack.peek();      p.mStatus = Cmd.CMD_RUN;      p.mCmd = Cmd.CMD_DELETE;      while (p.mStatus != Cmd.CMD_DELETE) {         Sleep(10);      }      if (mStack.size() != 0)         mStack.peek().mCmd = Cmd.CMD_RUN;   }   /**    * 停止辅助线程和循环任务线程,同时检查循环任务栈中的元素是否已经全部出栈    */   public static void close() {      if (mStack.size() > 0) {         L.e("TaskManager", "loop task 没有安全退出, 请检查你的程序,修复它.");      }      isThreadEnd = true;   }   /**    * 添加循环任务的辅助线程,理论上,这个线程可能会长期空闲    */   private static class AuxiliaryThread extends Thread {      @Override      public void run() {         while (!isThreadEnd) {            if (!mList.isEmpty()) {               Param p = mList.get(0);               if (p.mTask != null) {                  p.mTask.doWork(p.mParam);               }               mList.remove(0);            } else {               TaskManager.Sleep(10);            }         }         mList.clear();         tTTemp = null;      }   }   /**    * 实际执行循环任务的线程。循环任务线程是一个无限循环,每次取任务栈栈顶的任务执行。    */   private static class LoopTaskThread extends Thread {      @Override      public void run() {         while (!isThreadEnd) {            if (mStack.size() > 0) {               Param p = mStack.peek();               if (p.mCmd == Cmd.CMD_RUN && p.mTask != null) {                  if (p.isTimeTorun()) {                     p.setNextTime();            // 这么做似乎不太合理?是否应该改为完成以后延时?另外一种解决方案是,再增加一个字段设置两次循环之间至少等待多久                     p.mTask.doWork(p.mParam);                  }                  p.mStatus = Cmd.CMD_RUN;               } else if (p.mCmd == Cmd.CMD_DELETE) {                  mStack.pop();                  p.mStatus = Cmd.CMD_DELETE;               } else                  p.mStatus = Cmd.CMD_PAUSE;               Sleep(1);            } else               Sleep(10);         }         mStack.clear();         mTLoop = null;      }   }}

0 0
原创粉丝点击