我的第一个多线程源码

 最近网上值机电子客票后台开发,其中的有个需求要求一次导入多个PNR(Passenger Name Record),并且判断这些导入的PNR是否满足同时导入的要求,并且完成相关PNR信息的提取和整理。开始我按照一般的思路完成了需求的功能,然而我发现导入一个PNR一般都在2秒钟以上,要是网络不好的话4、5秒都出现过,所以对自己开发的功能很不满意,这样的程序自己都接受不了,何况真正在生产线上工作的客服人员呢?于是,并发提取PNR的念头产生了。对于刚刚工作,又对Java多线程不熟悉的我这也许是个挑战,因为我只是知道有多线程这个概念,而没有真正的去使用过,去实践过。于是我到网上去找资料,查API文档,终于把这个难题放倒了。

GetPnrInfo.java类提取Pnr信息,实现了Ruable接口:

package  com.feinar.cbs.ibe;

import  java.sql.Timestamp;
import  java.text.SimpleDateFormat;
import  java.util.ArrayList;
import  java.util.List;
import  java.util.Locale;
import  java.util.concurrent.CountDownLatch;

import  com.feinar.cbs.delivery.pojo.Deliveryorders;
import  com.feinar.cbs.flight.order.pojo.Passenger;
import  com.feinar.cbs.flight.order.pojo.Segment;
import  com.feinar.cbs.flight.order.pojo.SegmentId;
import  com.feinar.cbs.flight.order.pojo.Segmentprice;
import  com.feinar.cbs.flight.order.pojo.SegmentpriceId;
import  com.travelsky.ibe.client.FD;
import  com.travelsky.ibe.client.FDResult;
import  com.travelsky.ibe.client.FF;
import  com.travelsky.ibe.client.FFResult;
import  com.travelsky.ibe.client.pnr.PNRAirSeg;
import  com.travelsky.ibe.client.pnr.PNRContact;
import  com.travelsky.ibe.client.pnr.PNRInfant;
import  com.travelsky.ibe.client.pnr.PNRPassenger;
import  com.travelsky.ibe.client.pnr.PNRSSR;
import  com.travelsky.ibe.client.pnr.RT;
import  com.travelsky.ibe.client.pnr.RTResult;

public   class  GetPnrInfo  implements  Runnable  {

    
private final String ptype[][] = """CH""IN" }"成人""儿童""婴儿" } };

    
private String pnr;

    
private String errormsg;

    
private List<Passenger> passengerlist[];

    
private List<Segment> segmentlist;

    
private Deliveryorders deliveryorders;

    
private CountDownLatch latch;

    
public GetPnrInfo(String pnr, CountDownLatch latch) {
        
this.pnr = pnr;
        
this.latch = latch;
        
this.errormsg = "";
        
this.deliveryorders = new Deliveryorders();
        
this.segmentlist = new ArrayList<Segment>();
        
this.passengerlist = new ArrayList[3];
        
for (int i = 0; i < 3; i++{
            
this.passengerlist[i] = new ArrayList<Passenger>();
        }


    }


    
public GetPnrInfo(String pnr, String errormsg,
            List
<Passenger> passengerlist[], List<Segment> segmentlist,
            Deliveryorders deliveryorders, CountDownLatch latch) 
{
        
this.pnr = pnr;
        
this.errormsg = errormsg;
        
this.passengerlist = passengerlist;
        
this.segmentlist = segmentlist;
        
this.deliveryorders = deliveryorders;
        
this.latch = latch;
    }


    
public void run() {
        
try {
            parsePnr();
        }
 catch (Exception e) {
            
this.setErrormsg(e.getMessage());
        }

        latch.countDown();

    }


    
public void parsePnr() throws Exception {
        
try {
            RT rt 
= new RT();
            RTResult rtresult 
= new RTResult();
            rtresult 
= rt.retrieve(this.getPnr());
            
// System.out.println("****** "+this.getPnr());
            
// 获取Pnr中的旅客信息
            
// 获得证件号组,常旅客号组
            String foidcard[] = new String[rtresult.getPassengersCount()];
            String fqtvcard[] 
= new String[rtresult.getPassengersCount()];
            
for (int j = 0; j < rtresult.getSSRsCount(); j++{
                PNRSSR pnrssr 
= rtresult.getSSRAt(j);
                
// System.out.println(pnrssr.getPsgrID().substring(1)+" card
                
// "+pnrssr.getServeInfo().substring(12));
                if (pnrssr.getSSRType().equalsIgnoreCase("foid"))
                    foidcard[Integer.parseInt(pnrssr.getPsgrID().substring(
1)) - 1= pnrssr
                            .getServeInfo().substring(
12);
                
else if (pnrssr.getSSRType().equalsIgnoreCase("fqtv"))
                    fqtvcard[Integer.parseInt(pnrssr.getPsgrID().substring(
1)) - 1= pnrssr
                            .getServeInfo().substring(
12);
            }


            
// 获取成人组,儿童组 getPassengers
            for (int j = 0; j < rtresult.getPassengersCount(); j++{
                Passenger passenger 
= new Passenger();
                PNRPassenger pnrp 
= rtresult.getPassengerAt(j);
                passenger.setPsgname(pnrp.getName());
                passenger.setType(String.valueOf(pnrp.getType()));
                passenger.setPnrno(rtresult.getPnrcode());
                
// System.out.println("*** " + j + " **** " + foidcard[j]);
                passenger.setIdtype(foidcard[j].substring(02));
                passenger.setIdcard(foidcard[j].substring(
2, foidcard[j]
                        .indexOf(
"/")));
                passenger.setMembercardnumber(fqtvcard[j] 
== null ? null
                        : fqtvcard[j].substring(
2, fqtvcard[j].indexOf("/")));
                
this.passengerlist[pnrp.getType()].add(passenger);
                passenger 
= null;
            }

            foidcard 
= null;
            fqtvcard 
= null;

            
// 获取婴儿组 getInfants
            for (int j = 0; j < rtresult.getInfantsCount(); j++{
                Passenger passenger 
= new Passenger();
                passenger.setType(
"2");
                PNRInfant infant 
= rtresult.getInfantAt(j);
                passenger.setPsgname(infant.getName());
                passenger.setBirthdate(infant.getBrith());
                passenger.setCarriedby(rtresult.getPassengerAt(
                        Integer.parseInt(infant.getCarrier().substring(
1)) - 1)
                        .getName());
                
this.passengerlist[2].add(passenger);
                passenger 
= null;
            }


            
// 获取Pnr 中的航班信息
            
// 提取航段信息
            SimpleDateFormat format = new SimpleDateFormat(
                    
"yyyy-MM-dd HH:mm:ss");
            
for (int i = 0; i < rtresult.getAirSegsCount(); i++{
                Segment seg 
= new Segment();
                PNRAirSeg pnrseg 
= rtresult.getAirSegAt(i);
                seg.setId(
new SegmentId(nullnew Long(i)));
                seg.setCarrier(pnrseg.getAirNo().substring(
02));
                seg.setFlightno(pnrseg.getAirNo().substring(
2));
                seg.setDepairport(pnrseg.getOrgCity());
                seg.setArrairport(pnrseg.getDesCity());
                seg.setDeptime(
new Timestamp(format.parse(
                        pnrseg.getDepartureTime().toLocaleString()).getTime()));
                seg.setArrtime(
new Timestamp(format.parse(
                        pnrseg.getArrivalTime().toLocaleString()).getTime()));
                seg.setCabin(String.valueOf(pnrseg.getFltClass()));

                
// 查询机型
                FFResult ffr = new FFResult();
                
try {
                    ffr 
= new FF().flightTime(pnrseg.getAirNo(), pnrseg
                            .getDepartureTime());
                    seg.setPlanetype(ffr.getPlaneModel());
                }
 catch (Exception e) {
                    System.out.println(
"系统在查询航班 " + pnrseg.getAirNo()
                            
+ " 机型时出错;");
                    
throw new Exception("系统在查询航班 " + pnrseg.getAirNo()
                            
+ " 机型时出错;");
                }

                seg.setSeatstatus(pnrseg.getActionCode());
// 待定
                Segmentprice segmentprice = new Segmentprice();
                segmentprice.setCarrier(seg.getCarrier());
                segmentprice.setFlightno(seg.getFlightno());
                segmentprice.setCabin(seg.getCabin());
                segmentprice.setDepairport(seg.getDepairport());
                segmentprice.setArrairport(seg.getArrairport());
                segmentprice.setArrtime(seg.getArrtime());
                segmentprice.setFlightdate(seg.getDeptime());
                segmentprice.setPlanetype(seg.getPlanetype());
                segmentprice.setId(
new SegmentpriceId(null, seg.getId()
                        .getSegorder()));
                
// 查询价格
                FD fd = new FD();
                FDResult rdresult;
                
for (int j = 0; j < 3; j++{
                    
try {
                        SimpleDateFormat formater 
= new SimpleDateFormat(
                                
"ddMMMyy"new Locale("EN"));
                        rdresult 
= fd.findPrice(seg.getDepairport(), seg
                                .getArrairport(), 
""
                                
+ formater.format(seg.getDeptime().getTime())
                                        .toUpperCase(), seg.getCarrier(), seg
                                .getPlanetype(), ptype[
0][j]);
                        
for (int k = 0; k < rdresult.getElementNum(); k++{
                            
if (rdresult.getCabinType(k).equals(seg.getCabin())) {
                                
switch (j) {
                                
case 0:
                                    segmentprice
                                            .setAdultprice(Double
                                                    .valueOf(rdresult
                                                            .getSinglePrice(k)));
                                    
break;
                                
case 1:
                                    segmentprice
                                            .setChildprice(Double
                                                    .valueOf(rdresult
                                                            .getSinglePrice(k)));
                                    
break;
                                
case 2:
                                    segmentprice
                                            .setInfantprice(Double
                                                    .valueOf(rdresult
                                                            .getSinglePrice(k)));
                                    
break;
                                
default:
                                    
break;
                                }

                            }

                        }

                    }
 catch (Exception e1) {
                        System.out.println(
"系统在查询航班" + pnrseg.getAirNo() + ""
                                
+ ptype[1][j] + "价时出错;");
                        
throw new Exception("系统在查询航班" + pnrseg.getAirNo() + ""
                                
+ ptype[1][j] + "价时出错;");
                    }


                }

                seg.setSegmentprice(segmentprice);
                segmentlist.add(seg);
                segmentprice 
= null;
                seg 
= null;
                
// 获取配送联系人
                
// System.out.println(rtresult.getContactsCount());
                PNRContact contact = rtresult.getContactAt(0);
                String contactinfo[] 
= contact.getContact().split("/");
                String phone 
= "";
                
if (contactinfo.length == 1{
                    phone 
= contactinfo[0];
                }
 else {
                    deliveryorders.setContactname(contactinfo[
0]);
                    phone 
= contactinfo[1];
                }

                
if (phone.startsWith("0"))
                    deliveryorders.setContacttel(phone);
                
else
                    deliveryorders.setMobilephone(phone);
            }

        }
 catch (Exception e) {
            System.out.println(
"导入【" + pnr + "】出错;");
            
throw new Exception("导入【" + pnr + "】出错;");
        }


    }


    
public Deliveryorders getDeliveryorders() {
        
return deliveryorders;
    }


    
public void setDeliveryorders(Deliveryorders deliveryorders) {
        
this.deliveryorders = deliveryorders;
    }


    
public String getErrormsg() {
        
return errormsg;
    }


    
public void setErrormsg(String errormsg) {
        
this.errormsg = errormsg;
    }


    
public CountDownLatch getLatch() {
        
return latch;
    }


    
public void setLatch(CountDownLatch latch) {
        
this.latch = latch;
    }


    
public List<Passenger>[] getPassengerlist() {
        
return passengerlist;
    }


    
public void setPassengerlist(List<Passenger>[] passengerlist) {
        
this.passengerlist = passengerlist;
    }


    
public String getPnr() {
        
return pnr;
    }


    
public void setPnr(String pnr) {
        
this.pnr = pnr;
    }


    
public List<Segment> getSegmentlist() {
        
return segmentlist;
    }


    
public void setSegmentlist(List<Segment> segmentlist) {
        
this.segmentlist = segmentlist;
    }


}

LoadPnrAction.java多线程提取Pnr并判断是否满足条件,如果满足,则整合相关信息:

package  com.feinar.cbs.flight.order.struts.action;

import  java.util.ArrayList;
import  java.util.List;
import  java.util.concurrent.CountDownLatch;

import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletResponse;

import  org.apache.struts.action.Action;
import  org.apache.struts.action.ActionForm;
import  org.apache.struts.action.ActionForward;
import  org.apache.struts.action.ActionMapping;

import  com.feinar.cbs.delivery.pojo.Deliveryorders;
import  com.feinar.cbs.flight.order.pojo.Passenger;
import  com.feinar.cbs.flight.order.pojo.Segment;
import  com.feinar.cbs.ibe.GetPnrInfo;

public   class  LoadPnrAction  extends  Action  {
    @Override
    
public ActionForward execute(ActionMapping mapping, ActionForm webForm,
            HttpServletRequest request, HttpServletResponse response) 
{
        Long l 
= System.currentTimeMillis();
        String parseError 
= "在导入PNR时发生了以下错误:/n";
        String forword 
= "";
        
if (request.getParameter("forword"!= null
                
&& !"".equals(request.getParameter("forword"))) {
            forword 
= (String) request.getParameter("forword");
        }

        
if ("".equals("forword")) {
            parseError 
+= "/n    非法请求来源;    ";
            request.getSession().setAttribute(
"loadpnrError", parseError);
            
return mapping.findForward("tomainjsp");
        }

        String pnrs 
= ""// DKD4L/DKD4Q/DKD50
        
// DKD56
        if (request.getParameter("pnrs"!= null
                
&& !"".equals(request.getParameter("pnrs"))) {
            pnrs 
= (String) request.getParameter("pnrs");
        }
// "CSJB8/CSHMD/CSHMF/CSJBB/CSJB9";
        
// 获取pnr[]
        request.getSession().setAttribute("pnrs", pnrs);
        String pnr[] 
= pnrs.split("/");
        System.out.println(
"***  pnrs :" + pnrs);
        
if (pnr.length < 1{
            parseError 
+= "/n    请输入要导入的PNR,并控制在5个以内;    ";
            request.getSession().setAttribute(
"loadpnrError", parseError);
            
return mapping.findForward(forword);
        }

        
if (pnr.length > 5{
            parseError 
+= "/n    你输入了 " + pnr.length + " 个PNR,请控制在5个以内;    ";
            System.out.println(
"*****  parseError  " + parseError);
            request.getSession().setAttribute(
"loadpnrError", parseError);
            
return mapping.findForward(forword);
        }


        
// 解析pnr
        List<Passenger> passengerList = new ArrayList<Passenger>();
        List
<Segment> segmentList = new ArrayList<Segment>();
        Deliveryorders delivery 
= new Deliveryorders();
        
int pnrNum = pnr.length;
        Thread threads[] 
= new Thread[pnrNum];
        GetPnrInfo pnrInfo[] 
= new GetPnrInfo[pnrNum];
        CountDownLatch latch 
= new CountDownLatch(pnrNum);
        
for (int i = 0; i < pnrNum; i++{
            pnrInfo[i] 
= new GetPnrInfo(pnr[i], latch);
            threads[i] 
= new Thread(pnrInfo[i]);
            threads[i].start();    
//千万记住不能使用run()方法,否则就是简单的函数调用而不是多线程处理
        }

        
try {
            latch.await();
        }
 catch (InterruptedException exc) {

        }

        System.out.println(
"*******   " + pnrInfo[0].getSegmentlist());
        
boolean flag = false// 获取、解析PNR时是否发生错误标志

        
for (int i = 0; i < pnrInfo.length; i++{
            
if (!"".equals(pnrInfo[i].getErrormsg())) {
                flag 
= true;
                parseError 
+= "/n    " + pnrInfo[i].getErrormsg() + "    ";
            }

        }

        
if (flag) {
            System.out.println(
"解析Pnr时有错误,退出 " + parseError);
            System.out.println(
"***  PNR 解析耗时:  "
                    
+ (System.currentTimeMillis() - l));
            request.getSession().setAttribute(
"loadpnrError", parseError);
            
return mapping.findForward(forword);
        }

        
// 检测是否同天、同航段、同窗位
        List<Segment> seglist0 = pnrInfo[0].getSegmentlist();
        
for (int i = 1; i < pnrInfo.length; i++{
            List
<Segment> seglisti = pnrInfo[i].getSegmentlist();
            
if (seglisti.size() == seglist0.size()) {
                
for (int j = 0; j < seglist0.size(); j++{
                    
if (!seglisti.get(j).getCarrier().equals(
                            seglist0.get(j).getCarrier())
                            
|| !seglisti.get(j).getFlightno().equals(
                                    seglist0.get(j).getFlightno())
                            
|| !seglisti.get(j).getPlanetype().equals(
                                    seglist0.get(j).getPlanetype())
                            
|| !seglisti.get(j).getCabin().equals(
                                    seglist0.get(j).getCabin())
                            
|| !seglisti.get(j).getDeptime().equals(
                                    seglist0.get(j).getDeptime())) 
{
                        System.out.println(
"系统检测到【" + pnr[i] + "】与【"
                                
+ pnr[i - 1+ "】不是同天、同航段、同窗位,不能同时导入;");
                        parseError 
+= "/n    系统已检测到【" + pnr[i] + "】与【"
                                
+ pnr[i - 1+ "】不是同天、同航段、同窗位,不能同时导入;    ";
                        request.getSession().setAttribute(
"loadpnrError",
                                parseError);
                        System.out.println(
"***  PNR 解析已经耗时:  "
                                
+ (System.currentTimeMillis() - l));
                        
return mapping.findForward(forword);
                    }

                }

            }
 else {

                String samestr 
= "";
                
for (int j = 0; j < i; j++{
                    samestr 
+= "" + pnr[j];
                }

                samestr 
= samestr.substring(2);
                System.out.println(
"系统检测到【" + pnr[i] + "】与【" + samestr
                        
+ "】航段数不同,不能同时导入;");
                parseError 
+= "/n    系统已检测到【" + pnr[i] + "】与【" + samestr
                        
+ "】航段数不同,不能同时导入;    ";
                request.getSession().setAttribute(
"loadpnrError", parseError);
                System.out.println(
"***  PNR 解析已经耗时:  "
                        
+ (System.currentTimeMillis() - l));
                
return mapping.findForward(forword);
            }

        }

        seglist0 
= null;
        
// 航班信息 联系信息
        segmentList = pnrInfo[0].getSegmentlist();
        delivery 
= pnrInfo[0].getDeliveryorders();
        
// 整理旅客信息
        for (int i = 0; i < 3; i++{
            
for (int j = 0; j < pnrInfo.length; j++{
                
for (int k = 0; k < pnrInfo[j].getPassengerlist()[i].size(); k++{
                    passengerList.add(pnrInfo[j].getPassengerlist()[i].get(k));
                }

            }

        }

      

        request.getSession().setAttribute(
                
"data",
                
new Object[] null, segmentList, passengerList, nullnull,
                        
null, delivery, pnrs }
);
        System.out.println(
"***  PNR 解析耗时:  "
                
+ (System.currentTimeMillis() - l));
        
return mapping.findForward("input");

    }

}


现在导入1个PNR大概2-3秒,导入5个需3-4秒导入10个也才3-4秒,由于需求只要求最多导入5个,所以我就没有测更多的数据,反正满足需求就好,完成功能就OK,哈哈。
多线程操作实例源码 Windows是一个多任务的系统,如果你使用的是windows 2000及其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程。什么是进程呢?当一个程序开始运行时,它就是一个进程,进程所指包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。浏览器就是一个很好的多线程的例子,在浏览器中你可以在下载JAVA小应用程序或图象的同时滚动页面,在访问新页面时,播放动画和声音,打印文件等。   多线程的好处在于可以提高CPU的利用率——任何一个程序员都不希望自己的程序很多时候没事可干,在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。   然而我们也必须认识到线程本身可能影响系统性能的不利方面,以正确使用线程: 线程也是程序,所以线程需要占用内存,线程越多占用内存也越多 多线程需要协调和管理,所以需要CPU时间跟踪线程 线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题 线程太多会导致控制太复杂,最终可能造成很多Bug   基于以上认识,我们可以一个比喻来加深理解。假设有一个公司,公司里有很多各司其职的职员,那么我们可以认为这个正常运作的公司就是一个进程,而公司里的职员就是线程。一个公司至少得有一个职员吧,同理,一个进程至少包含一个线程。在公司里,你可以一个职员干所有的事,但是效率很显然是高不起来的,一个人的公司也不可能做大;一个程序中也可以只用一个线程去做事,事实上,一些过时的语言如fortune,basic都是如此,但是象一个人的公司一样,效率很低,如果做大程序,效率更低——事实上现在几乎没有单线程的商业软件。公司的职员越多,老板就得发越多的薪水给他们,还得耗费大量精力去管理他们,协调他们之间的矛盾和利益;程序也是如此,线程越多耗费的资源也越多,需要CPU时间去跟踪线程,还得解决诸如死锁,同步等问题。总之,如果你不想你的公司被称为“皮包公司”,你就得多几个员工;如果你不想让你的程序显得稚气,就在你的程序里引入多线程吧!
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值