Callable接口,实现多线程
1.实现 Callable接口,相较于实现 Runnable 接口的方式,优点是:方法可以有返回值,并且可以抛出异常
2.需要 FutureTask实现类的支持,用于接收运算结果
3.result.get(),接收返回的计算结果,在所有的线程没有执行完成之后这里是不会执行的
实现Callable接口
public class RealTimeRiskCallable implements Callable<RealTimeRisk> {private Logger logger =LoggerFactory.getLogger(RealTimeRiskThread.class);private String path;//文件路径private Integer count;//计算文件名称加的区别private List<String> deviceName;//设备名称private RealTimeRisk realTimeRisk=new RealTimeRisk();//接收风险计算的结果public RealTimeRiskCallable(String path, Integer count,List<String> deviceName) {this.path = path;this.count = count;this.deviceName = deviceName;}@Overridepublic RealTimeRisk call() throws Exception {try {String path=this.path;//到时候读取配置文件进行配置String bpaPath="BPA_EXE_PATH"+this.count;String realFilePath=path.substring(0,path.lastIndexOf("/"))+File.separator+"copyZh"+this.count+".dat";FileUtil.copyFile(path, realFilePath);//复制一个copyZh.dat文件,真正用这个path=realFilePath;new HealingDat().healing(path,bpaPath);ExecuteBPA bpa=ExecuteBPA.getANewInstance();Integer code = bpa.execute(path,bpaPath);if(code != 5) {System.err.println("dat文件计算出错!");}else{double lostdata=ElectricityUtil.getLoadData(bpa);//没有操作之前的负荷数据(损失负荷=操作之前的负荷数据-操作过后的负荷数据)ElectricityUtil.setNormalData(lostdata);//存放没有操作之前的负荷值ReadAndWriteDAT readAndWriteDAT =ReadAndWriteDAT.getANewInstance(path);EquipmentVo.setAutoStopBusCard(readAndWriteDAT.getAllNoteBCard());// 文件操作前注释的b卡(之后-之前=失压的母线)List<String> list2 =ElectricityUtil.countStation(bpa.readDatFile());EquipmentVo.setThridStationNames(list2);//这里借用了setThridStationNames这个存放值 System.out.println(lostdata);}logger.info("开始读取dat文件...");long start =System.currentTimeMillis();DataSourceUtil.replaceFileStr(path, this.deviceName);//进行dat对应操作long end =System.currentTimeMillis();logger.info("重新写入dat文件成功!耗时:"+(end-start)/1000+"S");realTimeRisk=new RealTimeRiskManagerImpl().nowRisk(path,bpaPath);//实时风险计算logger.info("实时风险计算成功!");} catch (Exception e) {logger.info("实时风险计算失败!");e.printStackTrace();}return realTimeRisk;}public void setCount(Integer count) {this.count = count;}public void setDeviceName(List<String> deviceName) {this.deviceName = deviceName;} }
调用:
/*** 多线程进行计算*/List<RealTimeRisk> allResult =new ArrayList<RealTimeRisk>();/*//测试数据list.clear();list.add("<name=南连乙线#type=线路>");list.add("<name=广生站#1主变#type=主变><name=广生站#2主变#type=主变>"); list.add("<name=广生站#2主变#type=主变>");*/ ExecutorService executorService = Executors.newCachedThreadPool();RealTimeRiskCallable realTimeRiskCallable1= null;RealTimeRiskCallable realTimeRiskCallable2= null;FutureTask<RealTimeRisk> result1=null;FutureTask<RealTimeRisk> result2=null;RealTimeRisk realTimeRisk=new RealTimeRisk();RealTimeRisk realTimeRisk2=new RealTimeRisk();long startTime=System.currentTimeMillis();path=tempPath;//最初的dat路径,上面进行过处理int minVale=0;int event=0;int temp=0;for (int i = 0; i < list.size(); i++) {/*** 目前发现5月份的dat和12月份的dat,两个bpa手动快速点击可以进行同时计算,但是最新的* 12月份的两个dat(修改过名称),不能同时计算,目前没有找到原因,因此多线程计算也会出现问题* 暂时先注释掉,还是先一个个计算,多线程需要修改i+=2* BPA_EXE_PATH1=C:\\psap32\\BIN\\pfnt.exe* BPA_EXE_PATH2=C:\\copypsap32\\psap32\\BIN\\pfnt.exe*/ // if(list.size()-i>=2){ // realTimeRiskCallable1= new RealTimeRiskCallable(path,1,Arrays.asList(list.get(i))); // realTimeRiskCallable2= new RealTimeRiskCallable(path,2,Arrays.asList(list.get(i+1))); // result1=new FutureTask<RealTimeRisk>(realTimeRiskCallable1); // result2=new FutureTask<RealTimeRisk>(realTimeRiskCallable2); // executorService.submit(result1);//Thread.sleep(5000); // executorService.submit(result2); // realTimeRisk=result1.get();//接收返回结果 // allResult.add(realTimeRisk); // realTimeRisk2=result2.get();//接收返回结果 // allResult.add(realTimeRisk2); // }else{realTimeRiskCallable1= new RealTimeRiskCallable(path,1,Arrays.asList(list.get(i)));result1=new FutureTask<RealTimeRisk>(realTimeRiskCallable1);executorService.submit(result1);realTimeRisk=result1.get();//接收返回结果 allResult.add(realTimeRisk); // }//获取事故事件等级最低的(不为零,等级越低,事故事件等级越高)event=Integer.parseInt(allResult.get(i).getAccidentEventRank());if(event!=0){if(temp==0){minVale=event;temp++;}else{if(event<minVale){minVale=event;}}}}long endTime=System.currentTimeMillis();logger.info("耗时:===>"+(endTime-startTime)/1000+"S");logger.info("===>所有风险计算完成!共有:"+allResult.size()+"条风险记录");