使用java语言,利用多线程调用WebService进行数据处理

来源:互联网 发布:淘宝vip 编辑:程序博客网 时间:2024/05/22 14:53
因工作原因,需要将一个表(tbA)中的所有数据,根据user_id,去请求webserive获取相关的数据,然后插入到另外的一张表(tbB)中,供他人使用。不过这个表中的数据不少有78万条左右,而这样的大批量数据操作,还不能白天执行。只能在夜里,等服务器负荷低的时候进行执行。考虑如果webservice的效率不高的时候,需要对数据进行分批执行操作。经过综合考虑,最后采用多线程技术(不过最后经过测试,效率还是不错78万条数据,使用10个线程操作,8个多小时就可以了)。
    首先在tbA表中,追加一个字段,deal_tag,这个字段为处理标志字段。该字段的数据默认为'0',如果需要分批处理,则可以设计部分数据中的该字段值为'1'。这个时候就可以读取了。考虑到服务器的负荷问题,采用的方案是读取一部分数据到缓冲区中,同时更改已经进入缓冲区中待处理的数据的deal_tag字段值为‘B’,标识该数据已经进入缓冲区中。对数据的处理,需要请求webservice。也就有可能是因为因为种种原因,webservice没有正常的返回数据,或者出现异常,而为了不让异常影响数据的处理,则每次处理完一条数据,将该数据放入另外的缓冲区中,如果请求WebService成功,标识数据的字段为'F',请求成功。如果因为WebService或者其他的原因导致失败,则标志该数据字段的deal_tag字段值为'E',等待下一次的调用调用处理。另外为了不增加数据库的负荷,等到缓冲区中的数据达到一定的数据,一次提交。而不采用处理一条数据,提交一条数据,这样效率太慢。核心代码如下(因不想透漏具体的表名,采用tbA,tbB,tbC代替):

点击(此处)折叠或打开

  1. import java.sql.ResultSet;
  2. import java.sql.SQLException;
  3. import java.util.ArrayList;
  4. import java.util.Collections;
  5. import java.util.List;

  6. import com.epro.DBUtility.CommonHelper;
  7. import com.epro.DBUtility.DBHelper;
  8. import com.epro.DBUtility.BatchData;
  9. public class FetchData implements Runnable {
  10.     
  11.     private int READ_COUNT = 500; //一次读取数据库多少条记录到缓冲区中

  12.     private int FLASH_BUFFER_COUNT = 2000; //处理后的数据,多少条进行提交到数据库

  13.     private List<UserInfo> userList = null;
  14.     private List<String> userStateSqlList = null; 
  15.     private List<BatchData> commitDataList = null;
  16.     
  17.     public FetchData(){
  18.         userList = Collections.synchronizedList(new ArrayList<UserInfo>());
  19.         userStateSqlList = new ArrayList<String>(); 
  20.         commitDataList = new ArrayList<BatchData>();
  21.     }
  22.     
  23.     //读取数据

  24.     private synchronized int readData(){
  25.         int result = 0;
  26.         String strSql = "SELECT user_id, serial_number, cust_name, eparchy_code, " + 
  27.             "detail_install_address, link_phone, service_code, cust_type, rate, " +
  28.             "in_date, deal_tag " +
  29.             "FROM tbA " +
  30.             "WHERE deal_tag in ('1','E') AND rownum <= " + READ_COUNT;
  31.         
  32.         ResultSet rs = null;
  33.         DBHelper db = new DBHelper();        
  34.         try {
  35.             rs = db.executeQuery(strSql);
  36.             while(rs.next()){
  37.                 UserInfo user = new UserInfo();
  38.                 user.setUserId(rs.getString("user_id"));
  39.                 user.setSerialNumber(rs.getString("serial_number"));
  40.                 user.setCustName(rs.getString("cust_name"));
  41.                 user.setEparchyCode(rs.getString("eparchy_code"));
  42.                 user.setDetailInstallAddress(rs.getString("detail_install_address"));
  43.                 user.setLinkPhone(rs.getString("link_phone"));
  44.                 user.setServiceCode(rs.getString("service_code"));
  45.                 user.setCustType(rs.getString("cust_type"));
  46.                 user.setRate(rs.getString("rate"));
  47.                 user.setInDate(rs.getString("in_date"));
  48.                 user.setDealTag(rs.getString("deal_tag"));
  49.                 
  50.                 userList.add(user); //放入队列中                

  51.                 ++result;
  52.             }
  53.         } catch (SQLException e) {
  54.             e.printStackTrace();
  55.         }finally{
  56.             try {
  57.                 rs.close();
  58.             } catch (SQLException e) {
  59.                 // TODO Auto-generated catch block

  60.                 e.printStackTrace();
  61.             }
  62.             finally{
  63.                 rs = null;
  64.             }
  65.             db.Close();
  66.         }
  67.         userIntoBuffer(); //将查询出来的数据,更改标志位为'B'

  68.         return result;
  69.     }
  70.     
  71.     private void userIntoBuffer(){
  72.         int buffersize = this.userList.size();
  73.         String sql = "";
  74.         String userID = "";
  75.         List<String> sqlList = new ArrayList<String>();
  76.         if(buffersize > 0){
  77.             DBHelper db = new DBHelper();    
  78.             for(int i=0; i<buffersize; i++){
  79.                 userID = userList.get(i).getUserId();
  80.                 sql = this.getUserStateSql(userID, "B");
  81.                 sqlList.add(sql);                
  82.             }
  83.             db.doBatch(sqlList); //批量进行数据处理

  84.             db.Close();
  85.         }
  86.     }
  87.     
  88.     private String getUserStateSql(String userID, String dealTag){
  89.         String result = "";
  90.         result = "UPDATE tbA SET deal_tag = '" + dealTag + 
  91.             "' WHERE user_id = " + userID;
  92.         
  93.         return result;
  94.     }
  95.     
  96.     public synchronized UserInfo getUserInfo(){
  97.         UserInfo result = null;
  98.         if(userList.size() > 0){
  99.             result = userList.remove(0);
  100.         }
  101.         return result;
  102.     }
  103.     
  104.     //开始进行数据的处理

  105.     public void beginDealData(){
  106.         ResInfo resInfo = null;
  107.         while(true){
  108.             UserInfo user = this.getUserInfo();
  109.             if(user != null && !"".equals(user.getUserId().trim())){ //当没有数据时,跳出循环

  110.                 //进行WebService请求,获取生产环境的资源数据,对数据进行解析,返回资源对象

  111.                 resInfo = getResInfo(user.getUserId());
  112.             }
  113.             else if(user == null){
  114.                 break;
  115.             }
  116.             else if(user != null && "".equals(user.getUserId().trim())){
  117.                 resInfo = new ResInfo();
  118.                 resInfo.out_err_id = "-1";
  119.                 resInfo.ln_line_flag = "0";
  120.                 resInfo.out_err_msg = "beginDealData is null.";
  121.                 System.out.println("user id is null.");
  122.             }
  123.             else{
  124.                 ;
  125.             }
  126.             userFinish(user, resInfo); //将用户的数据和资源的数据进行合并操作

  127.         }
  128.         int datacount = readData(); //读取表,看是否还有要处理的数据

  129.         if(datacount > 0){
  130.             beginDealData(); //递归调用,对需要处理的数据,进行继续读取

  131.         }
  132.         this.flashBuffer(); //做最后一次的提交处理后的buffer操作

  133.         System.out.println("finish at " + CommonHelper.getCurrentDateTime());
  134.     }
  135.     
  136.     public ResInfo getResInfo(String productID){
  137.         ResInfoReader myReader = new ResInfoReader();
  138.         return myReader.beginRequest(productID);
  139.     }
  140.     
  141.     //获取地区名称

  142.     public String getAreaName(String areaCode){
  143.         String result = "";
  144.         String strSql = "SELECT tb1.area_name area_name from " +
  145.         "tbC tb1 " +
  146.         "where tb1.area_code = ?";
  147.         String[] param = { areaCode };
  148.         ResultSet rs = null;
  149.         DBHelper db = new DBHelper();
  150.         rs = db.executeQuery(strSql, param);
  151.         try {
  152.             while(rs.next()){
  153.                 result = rs.getString("area_name");
  154.             }
  155.         } catch (SQLException e) {
  156.             // TODO Auto-generated catch block

  157.             e.printStackTrace();
  158.         } finally{
  159.             try {
  160.                 rs.close();
  161.             } catch (SQLException e) {
  162.                 // TODO Auto-generated catch block

  163.                 e.printStackTrace();
  164.             }
  165.             db.Close();
  166.         }
  167.         
  168.         return result;        
  169.     }
  170.     
  171.     private synchronized int userFinish(UserInfo user, ResInfo resInfo){
  172.         int result = 0;
  173.         String strSql = "";
  174.         String strAreaName = ""; //地区名称

  175.         String[] param = null;
  176.         if("".equals(user.getServiceCode())){ 
  177.             strAreaName = this.getAreaName(user.getEparchyCode());
  178.         }
  179.         else{
  180.             strAreaName = this.getAreaName(user.getServiceCode());
  181.         }
  182.         strSql = "INSERT INTO tbB(USER_ID, SERIAL_NUMBER, " +
  183.             "CUST_NAME, DEAL_TYPE, EPARCHY_CODE, DETAIL_INSTALL_ADDRESS, LINK_PHONE, " +
  184.             "EXCH_ID, LINEBOX_SEQ, LINEBOX, LINEBOX_ADDR, ROW_ID, COL_ID, VCOL_SEQ, " +
  185.             "PCABLE, PCABLE_SEQ, OCABLE, OCABLE_SEQ, FPCONNECT_ROW_ID, FPCONNECT_COL_ID, " + 
  186.             "FPCONNECT_SEQ, FCONNECT, FCONNECT_ADDR, FCONNECT_NAME, FOCONNECT_ROW_ID, " + 
  187.             "FOCONNECT_COL_ID, FOCONNECT_SEQ, SPCONNECT_ROW_ID, SPCONNECT_COL_ID, " + 
  188.             "SPCONNECT_SEQ, SCONNECT, SCONNECT_ADDR, SCONNECT_NAME, SOCONNECT_ROW_ID, " +
  189.             "SOCONNECT_COL_ID, SOCONNECT_SEQ, LN_FAC_CODE, LS_SWITCH_ID, LN_SWITCH_NAME, " +
  190.             "LS_SWITCH_MODE, LN_FAC_TYPE, LS_NODE_CODE, LS_NODE_ID, LS_MAC_CODE, LS_FRAME_CODE, " +
  191.             "LN_DHCOL_CODE, LS_FRAME_ID, LS_SLOT_ID, LS_PORT_ID, LN_DHCOL_SEQ, LN_LINE_ID, " +
  192.             "LN_LINE_FLAG, RELA_PRODUCT_NO, MEASURE_NAME, MEASURE_CODE, LINE_TYPE, REMOVE_FLAG, " +
  193.             "IN_TIME, OUT_TIME, EXCH_NAME, TRADE_ID, CUST_TYPE, RATE) VALUES(?, ?, ?, ?, ?, ?, " +
  194.             "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " +
  195.             "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, sysdate, null, " +
  196.             "?, ?, ?, ?)";
  197.         param = new String[]{
  198.                 user.getUserId(),
  199.                 user.getSerialNumber(),
  200.                 user.getCustName(),
  201.                 "",
  202.                 user.getEparchyCode(),
  203.                 user.getDetailInstallAddress(),
  204.                 user.getLinkPhone(),
  205.                 user.getServiceCode(),
  206.                 resInfo.linebox_seq,
  207.                 resInfo.linebox,
  208.                 resInfo.linebox_addr,
  209.                 resInfo.row_id,
  210.                 resInfo.col_id,
  211.                 resInfo.vcol_seq,
  212.                 resInfo.pcable,
  213.                 resInfo.pcable_seq,
  214.                 resInfo.ocable,
  215.                 resInfo.ocable_seq,
  216.                 resInfo.fpconnect_row_id,
  217.                 resInfo.fpconnect_col_id,
  218.                 resInfo.fpconnect_seq,
  219.                 resInfo.fconnect,
  220.                 resInfo.fconnect_addr,
  221.                 resInfo.fconnect_name,
  222.                 resInfo.foconnect_row_id,
  223.                 resInfo.foconnect_col_id,
  224.                 resInfo.foconnect_seq,
  225.                 resInfo.fpconnect_row_id,
  226.                 resInfo.fpconnect_col_id,
  227.                 resInfo.fpconnect_seq,
  228.                 resInfo.sconnect,
  229.                 resInfo.sconnect_addr,
  230.                 resInfo.sconnect_name,
  231.                 resInfo.soconnect_row_id,
  232.                 resInfo.soconnect_col_id,
  233.                 resInfo.soconnect_seq,
  234.                 resInfo.ln_fac_code,
  235.                 resInfo.ls_switch_id,
  236.                 resInfo.ln_switch_name,
  237.                 resInfo.ls_switch_mode,
  238.                 resInfo.ln_fac_type,
  239.                 resInfo.ls_node_code,
  240.                 resInfo.ls_node_id,
  241.                 resInfo.ls_mac_code,
  242.                 resInfo.ls_frame_code,
  243.                 resInfo.ln_dhcol_code,
  244.                 resInfo.ls_frame_id,
  245.                 resInfo.ls_slot_id,
  246.                 resInfo.ls_port_id,
  247.                 resInfo.ln_dhcol_seq,
  248.                 resInfo.ln_line_id,
  249.                 resInfo.ln_line_flag,
  250.                 resInfo.rela_product_no,
  251.                 resInfo.measure_name,
  252.                 resInfo.measure_code,
  253.                 resInfo.line_type,
  254.                 "0",
  255.                 strAreaName,
  256.                 "",
  257.                 user.getCustType(),
  258.                 user.getRate()    
  259.         };        

  260.         if("0".equals(resInfo.out_err_id)){
  261.             BatchData data = new BatchData(strSql, param);
  262.             commitDataList.add(data); //提交处理后的数据,到缓冲区

  263.             
  264.             result = 1;
  265.             strSql = this.getUserStateSql(user.getUserId(), "F");
  266.         }
  267.         else{
  268.             //当调用webservice后,不能正常的获取数据,则修改标志位为 'E'

  269.             strSql = this.getUserStateSql(user.getUserId(), "E");
  270.         }
  271.         userStateSqlList.add(strSql); //提交用户状态数据到缓冲区

  272.         checkBuffer();
  273.         //System.out.println("deal user id: " + user.getUserId() + " at " + CommonHelper.getCurrentDateTime());

  274.         return result;
  275.     }
  276.     
  277.     private void checkBuffer(){
  278.         if(userStateSqlList.size() >= FLASH_BUFFER_COUNT){
  279.             this.flashBuffer();
  280.         }
  281.     }
  282.     
  283.     private synchronized void flashBuffer(){
  284.         List<String> stateList = new ArrayList<String>();
  285.         List<BatchData> commitList = new ArrayList<BatchData>();
  286.         DBHelper db = new DBHelper();
  287.         
  288.         while(commitDataList.size()>0){
  289.             BatchData data112 = commitDataList.remove(0);
  290.             commitList.add(data112);
  291.         }
  292.         if(commitList.size() > 0){
  293.             db.doBatchData(commitList);
  294.         }
  295.         
  296.         while(userStateSqlList.size() > 0){
  297.             stateList.add(userStateSqlList.remove(0));
  298.         }
  299.         if(stateList.size() > 0){
  300.             db.doBatch(stateList);
  301.         }
  302.         
  303.         db.Close();
  304.         System.out.println("flash buffer at " + CommonHelper.getCurrentDateTime());
  305.     }

  306.     public void run() {        
  307.         this.beginDealData();        
  308.     }
  309. }
java调用WebService的代码如下:

点击(此处)折叠或打开

    其中webservice的操作,其中需要jar包,请下载apache.axis,XStream包,并加入到库中。其中axis主要是用来进行webServie请求用,而XStream主要使用将返回的XML数据,翻译为java对象。
    因为是java project项目,因此少不了main函数了。代码如下:

点击(此处)折叠或打开

  1. public class Shell {    
  2.     public static void main(String[] args){
  3.         boolean isthread = true;
  4.         FetchData fetch = new FetchData();    
  5.         if(isthread){            
  6.             new Thread(fetch).start();
  7.             new Thread(fetch).start();
  8.             new Thread(fetch).start();
  9.             new Thread(fetch).start();
  10.             new Thread(fetch).start();
  11.             new Thread(fetch).start();
  12.             new Thread(fetch).start();
  13.             new Thread(fetch).start();
  14.             new Thread(fetch).start();
  15.             new Thread(fetch).start();
  16.         }else{
  17.             ResInfo resInfo = fetch.getResInfo("productID"); 
  18.             System.out.println("out_err_id: " + resInfo.out_err_id);
  19.             System.out.println("out_err_msg: " + resInfo.out_err_msg);
  20.             System.out.println("linebox: " + resInfo.linebox);
  21.             System.out.println("linebox_addr: " + resInfo.linebox_addr);
  22.             System.out.println("pcable: " + resInfo.pcable);
  23.             System.out.println("ocable: " + resInfo.ocable);
  24.         }
  25.     }
  26. }
我在main函数中,使用了10个线程。可以根据具体的需要,进行线程的添加,减少。
0 0