- 浏览: 186369 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
iblike:
给我发一份,谢谢哦,iblike@163.com
Java实现的IP地址查询 - 性能不逊色于C -
编程的石头:
还可以再优化,你把地址库作一个分段,如1.1.1.1~63.1 ...
Java实现的IP地址查询 - 性能不逊色于C -
上官车月:
哥们 头像逆天啊
java Map排序(按key和按value) -
hwhwl:
给我也发一下吧 hwhwl@jpw.cn 我也需要这个
Java实现的IP地址查询 - 性能不逊色于C -
Longerandlonger:
return (o2.getValue() - o1.getV ...
java Map排序(按key和按value)
发现javaeye上的一个转载少了很多东西,重新转载一下,这个还是非常经典的!!!!
一. 它要能适应不同类型的请求:
本节用 makeString来说明要求有返回值的请求.用displayString来说明不需要返回值的请求.
二. 要能同时并发处理多个请求,并能按一定机制调度:
本节将用一个队列来存放请求,所以只能按FIFO机制调度,你可以改用LinkedList,就可以简单实现一个优先级(优先级高的addFirst,低的addLast).
三. 有能力将调用的边界从线程扩展到机器间(RMI)
四. 分离过度耦合,如分离调用句柄(取货凭证)和真实数据的实现.分离调用和执行的过程,可以尽快地将调返回.
现在看具体的实现:
public interface Axman {
Result resultTest(int count,char c);
void noResultTest(String str);
}
这个接口有两个方法要实现,就是有返回值的调用resultTest和不需要返回值的调用
noResultTest, 我们把这个接口用一个代理类来实现,目的是将方法调用转化为对象,这样就可以将多个请求(多个方法调)放到一个容器中缓存起来,然后统一处理,因为 Java不支持方法指针,所以把方法调用转换为对象,然后在这个对象上统一执行它们的方法,不仅可以做到异步处理,而且可以将代表方法调用的请求对象序列化后通过网络传递到另一个机器上执行(RMI).这也是Java回调机制最有力的实现.
一个简单的例子.
如果 1: 做A
如果 2: 做B
如果 3: 做C
如果有1000个情况,你不至于用1000个case吧?以后再增加呢?
所以如果C/C++程序员,会这样实现: (c和c++定义结构不同)
type define struct MyStruct{
int mark;
(*fn) ();
} MyList;
然后你可以声明这个结构数据:
{1,A,
2,B
3,C
}
做一个循环:
for(i=0;i<length;i++) {
if(数据组[i].mark == 传入的值) (数据组[i].*fn)();
}
简单说c/c++中将要被调用的涵数可以被保存起来,然后去访问,调用,而Java中,我们无法将一个方法保存,除了直接调用,所以将要调用的方法用子类来实现,然后把这些子类实例保存起来,然后在这些子类的实现上调用方法:
interface My{
void test();
}
class A implements My{
public void test(){
System.out.println(“A”):
}
}
class B implements My{
public void test(){
System.out.println(“B”):
}
}
class C implements My{
public void test(){
System.out.println(“C”):
}
}
class MyStruct {
int mark;
My m;
public MyStruct(int mark,My m){this.mark = amrk;this.m = m}
}
数组:
{ new MyStruct(1,new A()),new MyStruct(2,new B()),new MyStruct(3,new C())}
for(xxxxxxxxx) if(参数 ==数组[i].mark) 数组[i].m.test();
这样把要调用的方法转换为对象的保程不仅仅是可以对要调用的方法进行调度,而且可以把对象序列化后在另一台机器上执行,这样就把调用边界从线程扩展到了机器.
回到我们的例子:
class Proxy implements Axman{
private final Scheduler scheduler;
private final Servant servant;
public Proxy(Scheduler scheduler,Servant servant){
this.scheduler = scheduler;
this.servant = servant;
}
public Result resultTest(int count,char c){
FutureResult futrue = new FutureResult();
this.scheduler.invoke(new ResultRequest(servant,futrue,count,c));
return futrue;
}
public void noResultTest(String str){
this.scheduler.invoke(new NoResultRequest(this.servant,str));
}
}
其中scheduler是管理对调用的调度, servant是真正的对方法的执行:
Servant就是去真实地实现方法:
class Servant implements Axman{
public Result resultTest(int count,char c){
char[] buf = new char[count];
for(int i = 0;i < count;i++){
buf[i] = c;
try{
Thread.sleep(100);
}catch(Throwable t){}
}
return new RealResult(new String(buf));
}
public void noResultTest(String str){
try{
System.out.println("displayString :" + str);
Thread.sleep(10);
}catch(Throwable t){}
}
}
在scheduler 将方法的调用(invkoe)和执行(execute)进行了分离,调用就是开始”注册”方法到要执行的容器中,这样就可以立即返回出来.真正执行多久就是execute的事了,就象一个人点燃爆竹的引信就跑了,至于那个爆竹什么时候爆炸就不是他能控制的了.
public class Scheduler extends Thread {
private final ActivationQueue queue;
public Scheduler(ActivationQueue queue){
this.queue = queue;
}
public void invoke(MethodRequest request){
this.queue.putRequest(request);
}
public void run(){
while(true){
//如果队列中有请求线程,测开始执行请求
MethodRequest request = this.queue.takeRequest();
request.execute();
}
}
}
在scheduler中只用一个队列来保存代表方法和请求对象,实行简单的FIFO调用,你要实更复杂的调度就要在这里重新实现:
class ActivationQueue{
private static final int MAX_METHOD_REQUEST = 100;
private final MethodRequest[] requestQueue;
private int tail;
private int head;
private int count;
public ActivationQueue(){
this.requestQueue = new MethodRequest[MAX_METHOD_REQUEST];
this.head = this.count = this.tail = 0;
}
public synchronized void putRequest(MethodRequest request){
while(this.count >= this.requestQueue.length){
try {
this.wait();
}
catch (Throwable t) {}
}
this.requestQueue[this.tail] = request;
tail = (tail + 1)%this.requestQueue.length;
count ++ ;
this.notifyAll();
}
public synchronized MethodRequest takeRequest(){
while(this.count <= 0){
try {
this.wait();
}
catch (Throwable t) {}
}
MethodRequest request = this.requestQueue[this.head];
this.head = (this.head + 1) % this.requestQueue.length;
count --;
this.notifyAll();
return request;
}
}
为了将方法调用转化为对象,我们通过实现MethodRequest对象的execute方法来方法具体方法转换成具体对象:
abstract class MethodRequest{
protected final Servant servant;
protected final FutureResult future;
protected MethodRequest(Servant servant,FutureResult future){
this.servant = servant;
this.future = future;
}
public abstract void execute();
}
class ResultRequest extends MethodRequest{
private final int count;
private final char c;
public ResultRequest(Servant servant,FutureResult future,int count,char c){
super(servant,future);
this.count = count;
this.c = c;
}
public void execute(){
Result result = servant.resultTest(this.count,this.c);
this.future.setResult(result);
}
}
class NoResultRequest extends MethodRequest{
private String str;
public NoResultRequest(Servant servant,String str){
super(servant,null);
this.str = str;
}
public void execute(){
this.servant.noResultTest(str);
}
}
而返回的数据我们也将真实数据的获取和取货凭证逻辑分离:
package com.axman.jasync;
public abstract class Result {
public abstract Object getResult();
}
class FutureResult extends Result{
private Result result;
private boolean completed;
public synchronized void setResult(Result result){
this.result = result;
this.completed = true;
this.notifyAll();
}
public synchronized Object getResult(){
while(!this.completed){
try{
this.wait();
}catch(Throwable t){}
}
return this.result.getResult();
}
}
class RealResult extends Result{
private final Object result;
public RealResult(Object result){
this.result = result;
}
public Object getResult(){
return this.result;
}
}
OK,现在这个异步消息处理器已经有了模型,这个异步处理器中有昭雪些对象参与呢?
Servant 忠心做真实的事务
ActivationQueue将请求缓存起来以便调度
Scheduler对容器中的请求根据一定原则进行调度执行
Proxy将特定方法请求转换为特定对象
所有这些都是这个异步处理器的核心部件,虽然是核心部件,我们就要进行封装而不能随便让调用者来修改,所以我们用工厂模式(我KAO,我实在不想提模式但有时找不到其它词来表述)来产生处理器Axman对象:
package com.axman.jasync;
public class AxmanFactory {
public static Axman createAxman() {
Servant s = new Servant();
ActivationQueue queue = new ActivationQueue();
Scheduler st = new Scheduler(queue);
Proxy p = new Proxy(st,s);
st.start();
return p;
}
}
好了,我们现在用两个请求的产生者不停产生请求:
ResultInvokeThreadv 发送有返回值的请求:
package com.axman.jasync;
public class ResultInvokeThread extends Thread{
private final Axman ao;
private final char c;
public ResultInvokeThread(String name,Axman ao){
this.ao = ao;
this.c = name.charAt(0);
}
public void run(){
try{
int i = 0;
while(true){
Result result = this.ao.resultTest(i++,c);
Thread.sleep(10);
String = (String)result.getResult();
System.out.println(Thread.currentThread().getName() + " = " + );
}
}
catch(Throwable t){}
}
}
NoResultInvokeThread发送无返回值的请求:
package com.axman.jasync;
public class NoResultInvokeThread extends Thread{
private final Axman ao;
public NoResultInvokeThread(String name,Axman ao){
super(name);
this.ao = ao;
}
public void run(){
try{
int i = 0;
while(true){
String s = Thread.currentThread().getName() + i++;
ao.noResultTest(s);
Thread.sleep(20);
}
}
catch(Throwable t){}
}
}
对了,我们还需要一个什么东西来产生一个演示:
package com.axman.jasync;
public class Program {
public static void main(String[] args) {
Axman ao = AxmanFactory.createAxman();
new ResultInvokeThread("Axman",ao).start();
new ResultInvokeThread("Sager",ao).start();
new NoResultInvokeThread("Macke",ao).start();
}
}
看看结果吧.你可以把不同类型的请求不断地向处理器发送,处理器会不断地接收请求,放到队列中,并同时不断从队列中提出请求进行处理.
发表评论
-
JAXB 使用线程安全问题
2013-06-05 16:24 3504JAXB是一个 java bean与xml之间相互转换的非 ... -
Hashtable、HashMap区别,还是看源码印象深刻
2011-11-07 18:49 1095以前都是看别人谈 今天又想起这个问题,然后就自己看了看具体实 ... -
使用javamelody监控应用程序
2011-06-21 00:26 2201今天在网上看到开源的应用系统监控插件JavaMelody,ht ... -
IM4Java生成缩略图
2011-04-25 23:26 0了解了java自带的生成缩略图功能,以及一些纯java写的生成 ... -
Just For Easy 独家推出在线源码
2011-03-19 12:08 2013前几天发了一篇 Just For Easy 国内在线API,更 ... -
Just For Easy 国内在线API,更速度
2011-03-13 14:55 3596启用QQ 交流群:144615883,欢迎大家 加入交流。。。 ... -
利用JProfile检测Linux上Tomcat的内存泄露
2011-02-23 11:10 4083公司一系统开发完成上线后,经常出现系统宕机现象。开发环境MyE ... -
java Map排序(按key和按value)
2011-01-14 12:03 436001、按照key排序 对于java中Map的排序,有排序 ... -
【收藏】java中静态方法和非静态方法的存储
2010-10-28 10:53 3200将某 class 产生出一个 instance 之后,此 ... -
可爱的Jetty - tomcat的可能终结者
2010-09-20 14:50 3404有机会开始接触了一下Jetty,发现果然是好用,有一种相见恨晚 ... -
用JakartaCommon的net组建来做ftp文件传输【转载】
2010-09-16 15:26 1847package com.wwkj.cms.test.ftp; ... -
Java实现的IP地址查询 - 性能不逊色于C
2010-03-17 20:58 5353看到很多网站提供IP地址查询的服务,当时就想如此庞大的IP数据 ... -
HttpClient学习整理
2009-12-05 23:32 881HttpClient 学习整理 ... -
用POI的HSSF来控制EXCEL的研究
2009-11-16 12:37 7831.创建工作簿 (WORKBOOK) HSSFWorkb ... -
J2EE架构师手册中文 第一章
2009-09-04 11:19 0之前看到javaeye上有这么一个博客是翻译的这个, ... -
Nutch中MapReduce的分析
2009-08-09 10:22 1422作者:马士华 发表于:2008-03-06 20:11 最后更 ... -
birt动态报表参数的设置
2009-08-08 16:54 4612对于前面的sql语句已经写好,看看里面有几个?, ... -
birt初体验
2009-08-07 22:11 915这几天才开始看这个东西,还是很不错的,对于普通的报表的设计任务 ... -
让hibernate支持date_add
2009-08-07 21:55 2457今天做东西的时候想去查找某一天的记录数据,如果用单独的sql语 ... -
Apache和Subversion集成安装与配置
2009-08-04 20:37 835因为工作需要,要架设一个Subversion和Apache一起 ...
相关推荐
Java_异步消息处理
能同时并发处理多个请求,并能按一定机制调度: 用一个队列来存放请求,所以只能按FIFO机制调度,你可以改用LinkedList,就可以简单实现一个优先级(优先级高的addFirst,低的addLast). 三.有能力将调用的边界从线程扩展到...
javaEE 异步消息处理 服务端与客户端 1、客户端发送请求 服务端响应请求发送消息 客户端接受消息 2、过程:服务端一直发送消息 客户端一直接受放入容器里 容器里用线程去处理
Java-多线程异步请求统一响应结果 多线程异步请求是指在多个线程同时发起请求,并且在请求过程中不阻塞主线程的执行。这样可以提高程序的并发能力和响应速度。 需要注意的是,在实际的异步请求中,可能需要使用...
Servlet3.0 异步处理 页面推送 Comet 实例
_java中异步socket类的实现和源代码.doc
本文涉及Java编程中异步处理机制的简单介绍和一个相关实例,相信通过这篇文章,大家能对异步处理有更多的了解。
Android 提供了一个好用的工具---AsyncTask ,方便我们在子线程中对 UI 进行操作,AsyncTask 背后的实现原理也是基于异步消息处理机制的。
NULL 博文链接:https://ooft.iteye.com/blog/495158
java servlet 3 异步调用 异步处理 注册监听
本程序提供了一个多任务多线程异步处理框架。该框架使用简单,用户只需要继承抽象类Task,构建自己的任务类,再构造一个任务源,就可以轻松使用这个框架。 程序包里提供了一个例子Mytask 和MyTaskGenerator, 用户只...
2、异步交互模型,客户端将请求提交给Ajax引擎,客户端可以继续操作,由Ajax引擎来完成与服务武器端通信,当响应回来后,Ajax引擎会更新客户页面,在客户端提交请求后,用户可以继续操作,而无需等待 。
Java对io重新包装,大大提高了io的处理效率和复用率。可以用nio代替多线程编程。
java线程异步案例,以三个线程作为案例典型,同时发起三个线程,根据不同的订单领取各自的物品,自作过程同步处理。
所有的可以显示出来的图形元素都称为Component,Component代表了所有的可见的图形元素,... Pannel应用比较典型的就是Applet(JAVA的页面小应用程序),现在基本上已经不用了,AJAX和JAVASCRIPT完全取代了它的应用。
java中同步、异步的概念用的是相同的名字,却是有不同的含义
JAVA.NIO 异步长连接客户端与服务端都有,大家可以看看,另不知道怎么样将客户端读取的BUFF后的数据进行处理可以给出修改吗?
异步编程提供了一个非阻塞的,事件驱动的编程模型。 这种编程模型利用系统中多核执行任务来提供并行,因此提供了应用的吞吐率。此处吞吐率是指在单位时间内所做任务的数量。 在这种编程方式下, 一个工作单元将独立...
为了方便以后的开发,写了个异步多线程批处理的组件 具体用法见代码里的说明。很多时候都需要处理大批量数据,以后就方便多了
通常同步意味着一个任务的某个处理过程会对多个线程在用串行化处理,而异步则意味着某个处理过程可以允许多个线程同时处理。 异步通常代表着更好的性能,因为它很大程度上依赖于缓冲,是典型的使用空间换时间...