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()+"條風險記錄");
