多线程处理
来源:互联网 发布:淘宝旺铺模板页头 编辑:程序博客网 时间: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
- 多线程处理
- 多线程处理
- 多线程处理
- 多线程处理
- 多线程处理
- 多线程并发处理
- Delphi多线程处理(转载)
- SWT中处理多线程
- SWT中处理多线程
- C# 多线程控件处理
- C#的多线程处理
- Delphi多线程处理(转载)
- 多线程-异常处理
- java处理多线程并发
- 多线程的处理方式
- JNI 多线程的处理
- android 处理多线程 UserTask
- java 多线程异常处理
- 使用wsdl2java根据wsdl生成java客户端代码
- linux学习第七天
- 着色器:着色器语言&固定功能着色器
- Dell R910常见错误之 E1234告警
- openwebmail下载地址和配置
- 多线程处理
- Tomcat 调优及 JVM 参数优化
- log4j 不同的包(package)下的日志写入到不同的日志文件下
- 主题应用过程-framework
- SVN远程密码修改本地无法登陆的问题修复
- IBM x3850无法安装Citrix Xenserver6.0 处理一例(XEN) Scrubbing free RAM...
- 局域网QQ助手,查找局域网在线QQ,支持手机版QQ
- 通过DIH工具增量将MySQL表中的数据导入Solr时,last_index_time小于当前时间8小时的问题
- @media only screen 移动端设备查询判断