这个题目比较怪,听俺道来。俺一直在负责公司游戏服务器的开发和维护,日积月累下来终于将原本混乱的代码和结构重构的比较清晰了,在此过程中的体会就是,重构啊,不仅仅是技术活,更多是要克服不情愿的、得过且过的心理去做,去做了才发现麻烦并没有想象中的大。
改造过程中遇到这么个问题,我想将对某个创建的游戏的操作都固定在一个线程执行,与其他游戏可以并发地处理;或者说依据游戏id派发到某个固定的线程处理,对此游戏的操作都是串行化。不是俺不想彻底并行化,但是要将现有的代码改造成适应并行化相当困难,俺尝试的结果是问题百出,因此就想了这么个折中策略,不同游戏之间的操作可以并行,单个游戏内操作串行。怎么派发呢?很简单的机制,根据id%size结果来处理就好,size就是你准备开的线程数。因此可以很容易地模拟一个生产者消费者模型的线程池,根据游戏id%size的结果将任务塞到队列中,让生产者线程顺序处理。已经有部分代码是这样处理的,不过是自己实现的模型(BlockingQueue),比较不适合俺想要的任务式的处理过程,灵机一动,jdk5引入的线程池不是有个单线程的版本吗?俺将这个线程池再做个池不就OK了?说起来不好理解,看代码:
public interface Task extends Runnable {
public int getCode();
}
嗯,定义一个Task接口,继承Runnable,多了个getCode方法用于决定派发任务到哪个ExecutorService执行。线程池池登场:
public class SingleThreadPoolPool {
private Map<Integer, ExecutorService> threadPoolMap = new HashMap<Integer, ExecutorService>();
private int size;
public SingleThreadPoolPool(int size) {
this.size = size;
for (int i = 0; i < size; i++) {
ExecutorService executor = Executors.newSingleThreadExecutor();
threadPoolMap.put(i, executor);
}
}
public void execute(Task task) {
if (task == null)
return;
threadPoolMap.get(getIndex(task.getCode())).execute(task);
}
public void execute(int code, Runnable r) {
if (r == null)
return;
threadPoolMap.get(getIndex(code)).execute(r);
}
private int getIndex(int code) {
int index = -1;
if (code < 0)
index = 0;
else
index = code % this.size;
return index;
}
public void shutdown() {
for (int i = 0; i < size; i++) {
threadPoolMap.get(i).shutdown();
}
threadPoolMap.clear();
}
public int size() {
return this.size;
}
}
哇靠,这也太简单了,这就能保证code相同的任务会被排队顺序执行。是啊,很简单,不是啥高科技,但简单明了地实现了俺的需求。需要注意的是,只有通过Executor的execute方法提交的任务才会被排到队列中哦。
分享到:
相关推荐
最简单高效的JAVA对象池、线程池、以及使用对象池技术实现的数据库连接池 已在生产运行5年以上的代码 若有任何问题请与我联系
这是一个很简单的实现啦对象池与线程池的融合,方法的主要参数,线程池大小、对象池大小、对象的创建工厂(继承接口自己实现),执行时传入方面名称即可。(invoke方法第一个为参数为方法名,第二是可变参数(及方法...
里面是我个人通过模板来实现的通用池,并在通用池的基础上开发的一个线程池和数据库池。由于水平有限,所以开发的池可能比较简单。经过个人验证,这些池都是可用的,如有问题,可加QQ:970757285.
采用线程池 连接池 数据库 采用mysql,listcontr控件 右键菜单 此程序仅供学习 功能 增删改查学生,基本上各种非法操作验证都加了
服务端使用线程池实现。服务端主线程负责接收用 客户端请求,将客户端请求词封装成任务,再用锁机制 将任务添加到线程池中的任务队列中。工作线程通过互 斥量和条件变量访问任务队列,实现线程同步,使得线 程池...
libstpool是一个轻便高效的跨平台 支持win32 linux unix arm 的c语言线程池 任务池库 支持优先级任务
在Linux 系统下面用C 语言实现的高并发服务器的代码,具体用到了Epoll,线程池,数据库连接池。 具体可以看下连接http://blog.csdn.net/wuyuxing24/article/details/48758927
IOCP 内存池线程池的一个例子 主要优化在性能上 包括IO收发的重叠结构用了内存池技术
Linux 线程池 +连接池 ,备份学习。。。。。。。。。。。。。。。
corePoolSize:核心池的大小,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; ...
网上有现成的cthreadpool的代码,是c版的,且没有任务队列功能,不能做到任务的安全退出,根据实际需要写了一个c++版的,本程序实现了c++的封装,并实现了任务池和线程安全退出。弥补了c版的不足 在linux调试通过并...
关于SOCKET线程池,多个线程可否对同一个套接字同时写操作等问题?
线程池和mysql连接池的实现,可以在ubuntu12.04下完美实现,mysql连接池需要用到mysql-connector c++
共享 一起进步
libstpool是一个轻便高效的支持优先级的,跨平台的c语言 线程池,任务池库.
什么是线程池?简单点说,线程池就是有一堆已经创建好了的...当池子里的线程全都处理忙碌状态时,线程池中没有可用的空闲等待线程,此时,根据需要选择创建一个新的线程并置入池中,或者通知任务线程池忙,稍后再试。
文章目录一、关于线程池\进程池介绍1.1 池的概念1.2 池的划分1.3 线程池和进程池的区别1.5 进程池的创建(流程)二、创建线程池\进程池的两种方法2.1 concurrent和multiprocessing区别三、concurrent.futures模块3.1...
进程池与线程池学习ppt
当一个新任务需要运行时,如果线程 池中有等待的工作线程,就可以开始运行了;否则进入等待队列。 为什么要用线程池: 1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务 2.可以根据...