线程管理工具类(支持单线程队列以及多线程并发)
我们开发的过程中,如果某个动作耗时过长,我们又不想等待;如果某个动作需要定时不断执行;如果我们想同时做几件事情;我们就需要使用到线程了。线程里面运用最多的,无疑就是单线程的队列管理,或者多线程并发执行了。这种情况有1个经典的应用场景,也是个人至今做的唯一的一个J2ME项目中的运用:处理http请求。
那个是我工作第一年做的唯一的一个项目,对手机客户端开发感兴趣的应该有所了解,是移动的一个定制项目:手机阅读。现在已经全国推广使用了,各种机型应该都可以下载到适用的客户端。那个时候真的是个菜鸟,刚刚毕业,写起代码来就像摸着石头过河,一步一徘徊。团队里面有个工作第2年的算是老鸟的一个写手,处理http请求这块的内容,因为客户端与服务器之间是用http通讯的,所有数据都需要从服务端获取,在手机上展示,所以http工具类的重要性不言而喻,经过1个多月的反复推倒重来,测试修改,终于完工。其实代码并不多,核心的也就1个类,几百行而已。算下来,一个月平均每天也就码了40多行。至此,我对华为的那个团队负责人是深感佩服:他在编码开工会上说:“一个好的程序员,1天能写出的优秀代码也不过是百行不到,所以你们不要追求速度,慢慢来,质量最重要。”那个时候我们还在嗤之以鼻,1天少说也写个几百上千行啊,百行不到不是笑死人。之后大半年的时间,果然证明姜还是老的辣。我们花了2个月完成整个客户端代码的编写,却花了6个月在代码的review和重构上,也就是在那个时候,编码的一些好的习惯,以及对于代码质量的重视深深扎根在我心间。一直延续到如今的工作中。
当然很多做web项目的人不会有机会对代码做如此扣的动作,因为review和重构意味着工作量的增加,劳动成本的提升,开销的加大,这些都是你的上司所不希望见到的。他们常常希望你做出来的东西只要能用,满足条件即可,不会去关注代码的质量问题,时间是第一位的,因为要上线,要验收,要赚钱。当然,一些强大的web服务器足以弥补很多代码上的不足,所以一份好的代码越来越难出现在这样的队伍中。我目前处于的环境就是这样,万幸的是:我处于公司java组的框架开发团队,这使得我有机会延续之前好的习惯,感谢老天 ,没有让我去做枯燥无味的重复体力劳动(具体项目的开发)。
闲话不多说,回归主题。因为近期用到了线程,所以回想了之前项目中的使用场景:多线程并发(同时进行多本书的下载);单线程队列(一个页面上面普通的http请求,进行了队列的管理)。下面贴出核心代码。
包含2个文件:ThreadManageUtil ,ThreadObject 大家可以直接拷贝使用
import java.util.ArrayList;
import java.util.List;
/**
* 线程管理工具类
*
* @作者 komojoemary
* @version [版本号, 2011-2-24]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class ThreadManageUtil implements Runnable
{
/**
* 请求队列(用于单线程)
*/
private static List<ThreadObject> requestList = null;
/**
* 同步对象(用于单线程)
*/
private static Object object = new Object();
/**
* ThreadManageUtil对象的实例(用于单线程)
*/
private static ThreadManageUtil instance = null;
/**
* 当前的请求对象
*/
private ThreadObject currentRequest = null;
/**
* 是否为多线程运行
*/
private boolean isMultiThread = false;
/**
* 运行线程
*
* @param 无
* @return 无
* @exception/throws 无
* @see 无
*/
public void run() {
// 如果为多线程
if (isMultiThread) {
runHandle();
}
// 非多线程
else {
while (true) {
// 如果不为空则为超时需要重连的请求,不从队列里重新获取
if (currentRequest == null) {
synchronized (object) {
// 队列不为空
if (requestList.size() > 0) {
// 从队列中获取请求
currentRequest = (ThreadObject) requestList.get(0);
// 从请求队列中将当前请求删除
requestList.remove(0);
}
else {
try {
// 队列为空则交出对象锁,等待唤醒
object.wait();
continue;
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
runHandle();
currentRequest = null;
}
}
}
/**
*
* 请求过程处理 过程
*
* @param 无
* @return 无
* @exception/throws 无 无
* @see 无
*/
private void runHandle() {
try {
currentRequest.handleOperation();
Thread.yield();
}
catch (Exception ce) {
ce.printStackTrace();
}
}
/**
*
* 启动线程 当用单线程多任务排队请求时,将请求添加至请求队列中。当请求的是多线程时,开辟一个新的线程
*
* @param request
* 请求对象
* @return 无
* @exception/throws 无
*/
public static void sendRequest(ThreadObject request) {
// 多线程
if (request.isMultiThread()) {
ThreadManageUtil downloadHttp = new ThreadManageUtil();
downloadHttp.isMultiThread = true;
downloadHttp.currentRequest = request;
new Thread(downloadHttp).start();
}
else {
// 单线程请求排队
if (instance == null) {
// 在当前线程对象为空时才进行线程初始化操作,同时初始化队列
instance = new ThreadManageUtil();
requestList = new ArrayList<ThreadObject>();
new Thread(instance).start();
}
insertReqList(request);
}
}
/**
*
* 请求添加方法
*
* @param request
* 需要添加的请求
* @return 无
* @exception/throws 无
* @see 无
*/
private static void insertReqList(ThreadObject request) {
synchronized (object) {
requestList.add(request);
object.notify();
}
}
}
/**
* 线程执行对象
*
* @作者 komojoemary
* @version [版本号, 2011-2-24]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public abstract class ThreadObject
{
/**
* 是否多线程
*/
private boolean multiThread = false;
/**
* 是否处理完成
*/
private boolean isOk = false;
/**
* 线程处理操作
*
* @exception/throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public abstract Object handleOperation();
public boolean isMultiThread() {
return multiThread;
}
public void setMultiThread(boolean multiThread) {
this.multiThread = multiThread;
}
public boolean isOk() {
return isOk;
}
public void setOk(boolean isOk) {
this.isOk = isOk;
}
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步