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; } @Override public 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()+"条风险记录");