您的位置:首页 > 编程语言 > Java开发

Java.util.concurrent 包 使用Future,Callable实现抢答模式

2016-05-11 12:32 573 查看
我一直认为,在工作中总结是很必要的。尤其是自己刚刚发现了新大陆。比如java.util.concurrent 包的使用,之前我只是知道 Thread,Runnable。决心成为java大牛的我,在知道了concurrent 包后,一直在了解和编写示例。但是我感觉只有在实际应用中,我才能更深刻的掌握,机会终于来了。

我负责处理这样一个请求,请求传递给我一个证件号,我需要去请求两个webservice接口,因为不清楚,这个证件号通过哪个webservice才能正确的得到我想要的结果。

我觉得应该这样去设计,同时去请求两个webserice,谁先返回正确结果,就使用这个结果,同时让另一个中止工作。如果两个都没有返回正确的结果,则为异常。好像两个人进行抢答一样,下面是我写的代码。

/**
*
*
*/
public class FlightWebServiceInterface implements IFbtInvoking{

public static Logger logger = LoggerFactory.getLogger();

//工贸正式地址
public final  static String  url = "http://10.10.65.146:9080/pptpolicy/flightWS.ws";

/**
*
* @param idCardNumber 身份证号码
* @return  format xml
*/

public  String getXmlResultByNI(String idCardNumber) throws Exception{
try {
logger.info("start method String getXmlResultByNI(String idCardNumber), arg idCardNumber:"+idCardNumber);
// query airport message by idcard number
String urlname = url;
// new Service
Service s = new Service();
// build a Call via the new service object
Call call = (Call) s.createCall();
// set Timeout
call.setTimeout(new Integer(30000));
// set the remote method what will to invoke
call.setOperation("detrByNI");
// set the remote url address
call.setTargetEndpointAddress(urlname);
// set the arg need to transfer
call.addParameter("CardID",
org.apache.axis.encoding.XMLType.XSD_STRING,
javax.xml.rpc.ParameterMode.IN);// 接口的参数
call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);// 设置返回类型
logger.info("调用工贸接口 ,方法:detrByNI "+"参数  CardID :"+idCardNumber);
String result = (String) call.invoke(new Object[] { idCardNumber });
// 给方法传递参数,并且调用方法
logger.info("调用正常:"+idCardNumber);
return result;
} catch (Exception e) {
logger.info("调用工贸接口异常",e);
throw  e;

}
}

/**
*
* @param CardID
*            护照号码
* @return format xml
*/
public  String getXmlResultByPP(String CardID) throws Exception{
try {
//  logger.info("start method String getXmlResultByPP(String CardID), arg CardID:"+CardID);
// query airport message by passport number
String urlname = url;
// new Service
Service s = new Service();
// build a Call via the new service object
Call call = (Call) s.createCall();
// set Timeout
call.setTimeout(new Integer(30000));
// set the remote method what will to invoke
call.setOperation("detrByPP");
// set the remote url address
call.setTargetEndpointAddress(urlname);
// set the arg need to transfer
call.addParameter("CardID",
org.apache.axis.encoding.XMLType.XSD_STRING,
javax.xml.rpc.ParameterMode.IN);// 接口的参数
call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);// 设置返回类型
logger.info("调用工贸接口 ,方法:detrByPP "+"参数  CardID :"+CardID);
String result = (String) call.invoke(new Object[] { CardID });
// 给方法传递参数,并且调用方法
logger.info("调用正常:"+CardID);
return result;
} catch (Exception e) {
logger.info("调用工贸接口异常",e);
throw  e;
}

}

class RemoteNITask  implements Callable<String>{

private String id;

public RemoteNITask(String id) {
super();
this.id = id;
}

@Override
public String call() throws Exception {
String result = getXmlResultByNI(this.id);
return result;
}

}

class RemotePPTask implements Callable<String>{

private String id;

public RemotePPTask(String id) {
super();
this.id = id;
}

@Override
public String call() throws Exception {
String result = getXmlResultByPP(id);
return  result;
}

}

/**
* {@inheritDoc}
*/
@Override
public String getFbtResult(String id) {
ExecutorService service = Executors.newFixedThreadPool(2);
Future<String> fn = service.submit(new RemoteNITask(id));
Future<String> fp = service.submit(new RemotePPTask(id));
service.shutdown();
boolean  bn = false;
boolean  bp = false;
boolean  bbn = true;
boolean  bbp = true;

while(true){
if(fn.isDone() && !fn.isCancelled() && bbn){
try {
String result = fn.get();
logger.info("NI"+result);
if(!result.equals("") && result.indexOf("E00000")<0){
fp.cancel(true);
return result;
}else{
bn = true;
bbn= false;
}
} catch (Exception e){
bn = true;
bbn = false;
}
}
if(fp.isDone() && !fp.isCancelled() && bbp){
try {
String result = fp.get();
logger.info("PP"+result);
if(!result.equals("") && result.indexOf("E00000")<0){
fn.cancel(true);
return result;
}else{
bp = true;
bbp = false;
}
} catch (Exception e) {
bp = true;
bbp = false;
}
}
if(bn && bp){
return "";
}
}

}

public static void main(String[] args) {

IFbtInvoking o =  (IFbtInvoking) FbtProxy.getInstance("Z2538370");
String result = o.getFbtResult("Z2538370");
System.out.println(result);
}

}


getFbtResult 方法中实现了我的思路。同时提交两个任务去查询信息,在while(true) 无限循环里,去等待结果,谁先返回正确的信息,就直接返回,同时取消另一任务,如果两个都返回错误结果或者异常了,就跳出循环,如果有一个返回错误结果或者异常,就不再进入判断。

同时,我用动态代理,统计了请求接口的时间。

public class FbtProxy implements InvocationHandler {

public static Logger logger = LoggerFactory.getLogger();

private Object o;

private String id;

public FbtProxy(Object o,String id) {
super();
this.o = o;
this.id = id;
}

public static Object getInstance(String id){
IFbtInvoking origin = new FlightWebServiceInterface();
InvocationHandler handler  = new FbtProxy(origin, id);
Object o = Proxy.newProxyInstance(origin.getClass().getClassLoader(), origin.getClass().getInterfaces(), handler);
return o;

}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
long startTime=System.currentTimeMillis();   //获取开始时间
result = method.invoke(o, args);
long endTime=System.currentTimeMillis(); //获取结束时间
System.out.println("证件号"+this.id+"调用运行时间: "+(endTime-startTime)+"ms");
logger.info("证件号"+this.id+"调用运行时间: "+(endTime-startTime)+"ms");
return result;
}

}

文章写的粗糙,只是想分享出来,希望高手可以教我如何更快,性能更好的处理方式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: