最近项目中用到了 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();
}
}
还望各位大神求解啊java 异步 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();
}
}
还望各位大神求解啊java 异步 socket
2 server现在是全局变量,最好在addWork的时候,以参数的形式传进去。asynService.addWork(Asyn_ServiceTest.class,"startAccept", new Object[]{server}, back);public void startAccept(Object serverPara) {
ServerSocket server = (ServerSocket) serverPara;
// 省略
}
最好还是把异常的信息发出来吧。
异常信息如上, 报的是空指针
socket = server.accept(); 这行报错.
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楼
@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();
}
}
传递数据过去确实很有用, 问题解决了 真心感谢一楼的啊
产生新的实例后,全局变量都会重新初始化。你在addWork之前的所有赋值都会变得毫无意义了。->是不是最好把 startAccept单独写到一个类中??
这样显得更加的清晰,明了。这个类的职责就是一个worker类。
然后对 list 进行操作, 也就是说我想要 这个类和我其他 的类进行交互,但是 每次调用 的话都会重新初始化,
那我如何使他接收到的信息都储存起来呢,
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;
}
};