爲了簡化我的情況,我們假設我正在使用Java的Fork-Join框架實現二進制搜索。我的目標是在整數數組中找到一個特定的整數值(目標整數)。這可以通過將數組分成一半來完成,直到足夠小以執行串行搜索。算法的結果需要是一個布爾值,指示目標整數是否在數組中找到。向fork-join遞歸添加停止條件
在幻燈片28以後的Klaus Kreft's presentation中探索到類似的問題。但是,Kreft的目標是找到陣列中最大的數字,因此所有條目都必須進行掃描。在我的情況下,沒有必要掃描整個數組,因爲一旦找到目標整數,就可以停止搜索。
我的問題是,一旦我遇到目標整數,許多任務已經被插入到線程池中,並且我需要取消它們,因爲沒有繼續搜索的要點。我嘗試從RecursiveTask中調用getPool()。terminate(),但這並沒有什麼幫助,因爲許多任務已經排隊,我甚至注意到即使在關閉後調用新的隊列也是排隊的。
My目前的解決方案是使用一個靜態易失性布爾值,該值以'false'開始,並在任務開始時檢查其值。如果它仍然是'假',那麼任務開始工作,如果'真',任務立即返回。我實際上可以使用RecursiveAction。
所以我認爲這個解決方案應該可以工作,但是我想知道框架是否提供了一些處理這種情況的標準方式 - 即爲遞歸定義一個停止條件,從而取消所有排隊的任務。
請注意,如果我想要在找到目標整數(通過其中一個正在運行的任務)時立即停止所有正在運行的任務,則必須檢查這些任務中每行之後的布爾值,並且可能會影響性能,因爲值該布爾值不能被緩存(它被定義爲volatile)。
所以的確如此,我認爲需要一些標準的解決方案,並且可以通過清除隊列和插入正在運行的任務來提供。但我還沒有找到這樣的解決方案,我想知道是否有其他人知道它或有一個更好的主意。
謝謝您的時間, 阿薩夫
編輯:這裏是我的測試代碼:
package xxx;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class ForkJoinTest {
static final int ARRAY_SIZE = 1000;
static final int THRESHOLD = 10;
static final int MIN_VALUE = 0;
static final int MAX_VALUE = 100;
static Random rand = new Random();
// a function for retrieving a random int in a specific range
public static int randInt(int min, int max) {
return rand.nextInt((max - min) + 1) + min;
}
static volatile boolean result = false;
static int[] array = new int[ARRAY_SIZE];
static int target;
@SuppressWarnings("serial")
static class MyAction extends RecursiveAction {
int startIndex, endIndex;
public MyAction(int startIndex, int endIndex) {
this.startIndex = startIndex;
this.endIndex = endIndex;
}
// if the target integer was not found yet: we first check whether
// the entries to search are too few. In that case, we perform a
// sequential search and update the result if the target was found.
// Otherwise, we break the search into two parts and invoke the
// search in these two tasks.
@Override
protected void compute() {
if (!result) {
if (endIndex-startIndex<THRESHOLD) {
//
for (int i=startIndex ; i<endIndex ; i++) {
if (array[i]==target) {
result = true;
}
}
} else {
int middleIndex = (startIndex + endIndex)/2;
RecursiveAction action1 = new MyAction(startIndex, middleIndex);
RecursiveAction action2 = new MyAction(middleIndex+1, endIndex);
invokeAll(Arrays.asList(action1,action2));
}
}
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
for (int i=0 ; i<ARRAY_SIZE ; i++) {
array[i] = randInt(MIN_VALUE, MAX_VALUE);
}
target = randInt(MIN_VALUE, MAX_VALUE);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(new MyAction(0,ARRAY_SIZE));
System.out.println(result);
}
}
你能發表一些代碼嗎?您可以使用可以清除的特定隊列,也可以中斷正在運行的線程,但查看代碼更容易爲您提供適當的建議。 – 2014-09-04 12:36:49
我維護一個開源的fork/join框架,它提供了一個並行的順序搜索來處理您對「find first」的需求。您可以按原樣使用它,也可以使用代碼作爲如何自行完成的示例。 sourceForge鏈接是:http://sourceforge.net/projects/tymeacdse/?source=navbar – edharned 2014-09-04 13:58:18
謝謝@edharned,我會看看。它依賴於Java的fork/join框架嗎?你也使用volatile boolean/AtomicBoolean來停止搜索嗎? – Assaf 2014-09-04 14:25:36