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

来源:互联网 发布:订票助手 mac版 编辑:程序博客网 时间:2024/05/16 23:32

我一直认为,在工作中总结是很必要的。尤其是自己刚刚发现了新大陆。比如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;    }}文章写的粗糙,只是想分享出来,希望高手可以教我如何更快,性能更好的处理方式。
0 0