所以我編寫的應用程序,旨在執行Monte Carlo模擬研究,可以通過莫蘭過程(進化圖論)進化圖。對於無向圖而言,這種方法非常完美,但對於有向圖而言,應用程序一直表現出奇怪的行爲,我不能爲了我的生活找出原因。看起來會發生的事情是,當這個布爾變量isDirected設置爲true時,儘管在isDirected爲false時正常工作,但線程在循環條件滿足之前退出它們運行的for循環。
這些圖由一個鄰接矩陣表示,所以當圖被引導時代碼中的唯一區別是鄰接矩陣是非對稱的,但是我看不到任何會產生影響的原因。
代碼
主要相關的代碼是從控制器本節:
//Initialise a threadPool and an array of investigators to provide each thread with an Investigator runnable
long startTime = System.nanoTime();
int numThreads = 4;
Investigator[] invArray = new Investigator[numThreads];
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
//Assign the tasks to the threads
for(int i=0;i<numThreads;i++){
invArray[i] = new Investigator(vertLimit,iterations,graphNumber/numThreads,isDirected,mutantFitness,vertFloor);
threadPool.submit(invArray[i]);
}
threadPool.shutdown();
//Wait till all the threads are finished, note this could cause the application to hang for the user if the threads deadlock
try{
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}catch(InterruptedException except){
System.out.println("Thread interrupted");
}
//The next two blocks average the results of the different threads into 1 array
double[] meanArray = new double[vertLimit];
double[] meanError = new double[vertLimit];
double[] fixProbArray = new double[vertLimit];
double[] fixProbError = new double[vertLimit];
for(int x=0;x<vertLimit;x++){
for(Investigator i:invArray){
meanArray[x] += i.getMeanArray()[x];
meanError[x] += Math.pow(i.getMeanError()[x], 2);
fixProbArray[x] += i.getFixProbArray()[x];
fixProbError[x] += Math.pow(i.getFixProbError()[x], 2);
}
meanArray[x] = meanArray[x]/numThreads;
fixProbArray[x] = fixProbArray[x]/numThreads;
meanError[x] = Math.sqrt(meanError[x]);
fixProbError[x] = Math.sqrt(fixProbError[x]);
}
long endTime = System.nanoTime();
//The remaining code is for printing and producing graphs of the results
除了研究者類,它的如下所示的重要部件:
public class Investigator implements Runnable{
public Investigator(int vertLimit,int iterations,int graphNumber,Boolean isDirected,int mutantFitness,int... vertFloor){
//Constructor just initialises all the class variables passed in
}
public void run(){
GraphGenerator g = new GraphGenerator();
Statistics stats = new Statistics();
//The outer loop iterates through graphs with increasing number of vertices, this is the problematic loop that exits too early
for(int x = vertFloor>2?vertFloor:2; x < vertLimit; x++){
System.out.println("Current vertex amount: " + x);
double[] currentMean = new double[graphNumber];
double[] currentMeanErr = new double[graphNumber];
double[] currentFixProb = new double[graphNumber];
double[] currentFixProbErr = new double[graphNumber];
//This loop generates the required number of graphs of the given vertex number and performs a simulation on each one
for(int y=0;y<graphNumber;y++){
Simulator s = new Simulator();
matrix = g.randomGraph(x, isDirected, mutantFitness);
s.moranSimulation(iterations, matrix);
currentMean[y] = stats.freqMean(s.getFixationTimes());
currentMeanErr[y] = stats.freqStandError(s.getFixationTimes());
currentFixProb[y] = s.getFixationProb();
currentFixProbErr[y] = stats.binomialStandardError(s.getFixationProb(), iterations);
}
meanArray[x] = Arrays.stream(currentMean).sum()/currentMean.length;
meanError[x] = Math.sqrt(Arrays.stream(currentMeanErr).map(i -> i*i).sum());
fixProbArray[x] = Arrays.stream(currentFixProb).sum()/currentFixProb.length;
fixProbError[x] = Math.sqrt(Arrays.stream(currentFixProbErr).map(i -> i*i).sum());;
}
}
//A number of getter methods also provided here
}
問題
我已經放了一些打印語句,以瞭解發生了什麼事情,並且由於某種原因,當我將isDirected設置爲true時,線程在x到達vertLimit(我檢查過的確實是我指定的值)之前完成。我已經嘗試手動使用我的GraphGenerator.randomGraph()方法的有向圖,它給出了正確的輸出以及測試Simulator.moranSimulation(),這也適用於手動調用時的有向圖,並且我沒有得到線程中斷被我的catch塊捕獲,所以這也不是問題。
對於同一組參數,線程在不同的階段看起來是隨機的,有時它們在停止時都處於相同的x值,有時某些線程會比其他線程更進一步,跑步跑步。
我完全難住在這裏,真的很感謝一些幫助,謝謝。
由於未處理的異常,您的線程可能會中止。試着抓住每次調用submit()返回的Future對象,一旦你有了所有未來的集合,就調用每一個的.get()方法。在即使你的線程拋出異常的情況下,.get()也會拋出一個ExecutionException,它包含了實際拋出的異常,然後你可以進行調查。 – djmorton 2015-03-02 20:25:13
您也可以考慮使用ExecutorService的.invokeAll()方法,該方法將阻塞,直到所有任務完成,然後返回Future對象的集合。這可能比使用.shutdown()和awaitTermination()來確定你的任務完成的時候更習慣。 – djmorton 2015-03-02 20:28:05
@djmorton非常感謝你,我之前沒有看到Future界面!事實證明,這是由統計類中的問題引起的零誤差除以有向圖。感謝所有的建議傢伙! – dl101 2015-03-02 21:16:13