Java中异步调用如何实现

納蓝的天空 2013-06-26 05:35:36
最近项目中用到了 socket 服务器 异步处理信息
访问量有万人左右,
开始用的是 java的 NIO 非阻塞模式配置的 socket 但是 运行起来还是会有阻塞情况发生,

部分代码:
private void initTCP(int port){
try {
//分别实例化一个选择器,一个服务器端可选择通道
selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();

ssc.socket().bind(new InetSocketAddress(port));
// 设置非阻塞 注册信息
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT);

threadSelector.start();

} catch (IOException e) {
e.printStackTrace();
}
}

private InetAddress TCP_IP = null;
private int TCP_PORT = 0;
Thread threadSelector = new Thread(){
public void run(){
try {

while(true){
// 选择 select 得到 连接数 这里会出现 阻塞 直到有连接为止
selector.select();
TCPiterator = selector.selectedKeys().iterator();

new Thread(){
public void run(){
while(TCPiterator.hasNext()){
SelectionKey selectionKey = TCPiterator.next();

TCPiterator.remove(); // 删除此消息
// 在当前线程内处理
handlerSelectionKey(selectionKey);
}
}
}.start();

}
} catch (IOException e) {
e.printStackTrace();
}
}
};


这样编写人一多就会卡死的,
在网上看到异步的调用模式,用到 AsynService 方法
但是百度上找了很多都没有相关的资料,只有几篇 google 上的 例子代码,
http://code.google.com/p/asyn4j/wiki/user_guide
http://www.iteye.com/topic/746277

照着做了一遍后,发现
直接调用 测试 方法可以运行, 然后把我的 socket 放进去后一直报 空指针错误

测试方法直接可以用:
public void asyinit() throws IOException{
server=new ServerSocket(10000);
AsynService asynService = AsynServiceImpl.getService(300,3000L,3,2,2000L);
// 启动服务
asynService.init();
// 异步回调对象
AsynCallBack back = new AsynCallBack() {

@Override
public void doNotify() {
// startAccept();
abc();
}
};
for(int i=0;i<100;i++){
// 添加异步工作 - TargetService 的test 方法,方法参数 asynej+i
asynService.addWork(Asyn_ServiceTest.class,"abc", new Object[]{}, back);
// asynService.addAsynWork(new AsynWorkEntity(Asyn_ServiceTest.class,"startAccept"));
}
}

public void abc(){
System.out.println("回调函数");

}


加上自己的 socket 就报错

public void asyinit() throws IOException{
server=new ServerSocket(10000);
AsynService asynService = AsynServiceImpl.getService(300,3000L,3,2,2000L);
// 启动服务
asynService.init();
// 异步回调对象
AsynCallBack back = new AsynCallBack() {

@Override
public void doNotify() {
startAccept();
// abc();
}
};
for(int i=0;i<100;i++){
// 添加异步工作 - TargetService 的test 方法,方法参数 asynej+i
asynService.addWork(Asyn_ServiceTest.class,"startAccept", new Object[]{}, back);
// asynService.addAsynWork(new AsynWorkEntity(Asyn_ServiceTest.class,"startAccept"));
}
}


public void startAccept(){
try{
socket=server.accept();
// 侦听信息

}catch(Exception e){
e.printStackTrace();
}

}



还望各位大神求解啊
...全文
6501 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
納蓝的天空 2013-06-27
  • 打赏
  • 举报
回复
或者说是 AsynService 中有没有什么机制能回传 一些参数 呢, 我看了下这下面这个方法, 里面有个 AsynCallBack call() 这个方法, 是不是有用呢, 如果 是的话该如何使用呢,
AsynWork asynWork = new AsynWork() {
			
			@Override
			public int getWeight() {
				// TODO Auto-generated method stub
				return 0;
			}
			
			@Override
			public String getThreadName() {
				// TODO Auto-generated method stub
				return null;
			}
			
			@Override
			public AsynCallBack getAnycResult() {
				// TODO Auto-generated method stub
				return null;
			}
			
			@Override
			public AsynCallBack call() throws Exception {
				// TODO Auto-generated method stub
				return null;
			}
		};
納蓝的天空 2013-06-27
  • 打赏
  • 举报
回复
现在我要实现的是在 startAccept 中进行接收用户的信息 每接收一个就记录下来放到一个 list 中 然后对 list 进行操作, 也就是说我想要 这个类和我其他 的类进行交互,但是 每次调用 的话都会重新初始化, 那我如何使他接收到的信息都储存起来呢,
晓风吹雾 2013-06-27
  • 打赏
  • 举报
回复
->追问: 产生新的实例后, 会不会对实例里的其他 数据操作有影响 产生新的实例后,全局变量都会重新初始化。你在addWork之前的所有赋值都会变得毫无意义了。 ->是不是最好把 startAccept单独写到一个类中?? 这样显得更加的清晰,明了。这个类的职责就是一个worker类。
納蓝的天空 2013-06-27
  • 打赏
  • 举报
回复
追问: 产生新的实例后, 会不会对实例里的其他 数据操作有影响.是不是最好把 startAccept单独写到一个类中??
納蓝的天空 2013-06-27
  • 打赏
  • 举报
回复
			back = new AsynCallBack() {
				@Override
				public void doNotify() {
				
					startAccept(server);
					asynService.addWork(Asyn_ServiceTest.class,"startAccept", new Object[]{server}, back);
				}
			};
			// 添加异步工作 - TargetService 的test 方法,方法参数 asynej+i
				asynService.addWork(Asyn_ServiceTest.class,"startAccept", new Object[]{server}, back);
			//	asynService.addWork(TargetService.class, "test",new Object[]{"abc"},new TargetBack());

	}
	
	public void startAccept(Object serverPra){
		try{
			ServerSocket server = (ServerSocket) serverPra;
			System.out.println(server);
		socket=server.accept();
		System.out.println(socket.getInetAddress()+":"+socket.getPort()+"\tcome in");
		
		// 侦听信息
		
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}
传递数据过去确实很有用, 问题解决了 真心感谢一楼的啊
晓风吹雾 2013-06-27
  • 打赏
  • 举报
回复

asynService.addWork(Asyn_ServiceTest.class,"startAccept", new Object[]{server}, back);
这句话应该是产生了Asyn_ServiceTest的新的实例,而你的server这个变量估计没有定义成static的,如果没有定义为static的,那么Asyn_ServiceTest产生新的实例后,server这个变量就是null. 而下面的赋值语句,根本就没作用,因为你产生了新的实例Asyn_ServiceTest。

server=new ServerSocket(10000);

public void startAccept(){
        try{
        socket=server.accept();
        // 侦听信息
         
        }catch(Exception e){
            e.printStackTrace();
        }
         
    }
以上的方法的执行实例是新产生的,而你又没有给server赋值,所以就nullPointerException了 建议还是以参数的形式将server传进去。见1楼
納蓝的天空 2013-06-27
  • 打赏
  • 举报
回复

异常信息如上, 报的是空指针
socket = server.accept(); 这行报错.
晓风吹雾 2013-06-26
  • 打赏
  • 举报
回复
1 错误的stack异常信息,不然不大好分析。 2 server现在是全局变量,最好在addWork的时候,以参数的形式传进去。

asynService.addWork(Asyn_ServiceTest.class,"startAccept", new Object[]{server}, back);

public void startAccept(Object serverPara) {
    ServerSocket server = (ServerSocket) serverPara;
    // 省略
}
最好还是把异常的信息发出来吧。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧