【发布时间】:2021-02-11 09:04:51
【问题描述】:
我正在使用一堆可调用对象来搜索单个块中的列表,一旦返回 true,我想取消所有其他正在运行的可调用对象。 future.cancel 不会取消它们
我的号码查找器
public class NumberFinderImpl implements NumberFinder {
// how many threads the exucutor will use to start the callables
private final int NUMBER_THREADS = 20;
// the amount of elements in the array we will search in each callable chunk
private final int CHUNK_ARRAY_SIZE = 5;
@Override
public boolean contains(int valueToFind, List<CustomNumberEntity> arrayToSearch) {
long startTime = System.nanoTime();
ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(NUMBER_THREADS);
CompletionService<Boolean> completionService =
new ExecutorCompletionService<>(WORKER_THREAD_POOL);
int numberOfChunksNeeded = (int) Math.ceil(arrayToSearch.size() / CHUNK_ARRAY_SIZE);
// get a callable for each chunk search
List<Callable<Boolean>> callablesForEachChunkSearch =
getCallablesForEachChunk(
CHUNK_ARRAY_SIZE, numberOfChunksNeeded, valueToFind, arrayToSearch);
// start the callables and collect the futures
List<Future<Boolean>> futuresForCallables =
callablesForEachChunkSearch
.stream()
.map(completionService::submit)
.collect(Collectors.toList());
for (int j = 0; j < futuresForCallables.size(); j++) {
try {
// take().get() is blocking
// so if a callable is not done yet
// it will wait until it is before proceeding
Boolean chunkResult = completionService.take().get();
if (chunkResult) {
long endTime = System.nanoTime();
long timeTaken = endTime - startTime;
// TimeUnit
long timeInSeconds = TimeUnit.SECONDS.convert(timeTaken, TimeUnit.NANOSECONDS);
System.out.println("Search time in seconds" + timeInSeconds);
for (Future<Boolean> future : futuresForCallables) {
// cancel all the other running callables
future.cancel(true);
}
return true;
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
for (Future<Boolean> future : futuresForCallables) {
// cancel all the other running callables
future.cancel(true);
}
long endTime = System.nanoTime();
long timeTaken = endTime - startTime;
// TimeUnit
long timeInSeconds = TimeUnit.SECONDS.convert(timeTaken, TimeUnit.NANOSECONDS);
System.out.println("Search time in seconds" + timeInSeconds);
return false;
}
// get a list of callables that each search a certain chunk of the array
private List<Callable<Boolean>> getCallablesForEachChunk(
int chunkArraySize,
int numberOfChunksNeeded,
int valueToFind,
List<CustomNumberEntity> arrayToSearch) {
List<Callable<Boolean>> callableList = new ArrayList<>(numberOfChunksNeeded);
for (int i = 0; i < numberOfChunksNeeded; i++) {
int startPosForCallable = 0;
if (i > 0) {
startPosForCallable = i * chunkArraySize;
}
// dont let end pos go out of bounds
// if the chunk extends past the size, just set endPos as the end of the array
int endPosForCallable =
Math.min(startPosForCallable + chunkArraySize - 1, arrayToSearch.size());
Callable<Boolean> callableSearch =
new NumberFinderCallable(
arrayToSearch, valueToFind, startPosForCallable, endPosForCallable);
callableList.add(callableSearch);
}
return callableList;
}
进行搜索的我的可调用对象
public class NumberFinderCallable implements Callable<Boolean> {
private List<CustomNumberEntity> arrayToSearch;
private int startPos;
private int endPos;
private int valueToSearchFor;
public NumberFinderCallable(
List<CustomNumberEntity> arrayToSearch, int valueToSearchFor, int startPos, int endPos) {
this.arrayToSearch = arrayToSearch;
this.startPos = startPos;
this.endPos = endPos;
this.valueToSearchFor = valueToSearchFor;
}
@Override
public Boolean call() {
System.out.println(
"Callable started, searching the chunk of array with start pos "
+ startPos
+ " and end pos "
+ endPos);
for (int i = startPos; i <= endPos; i++) {
System.out.println(
"Callable is comparing a number in pos "
+ i
+ " in the chunk with star pos "
+ +startPos
+ " and end pos "
+ endPos);
if (FastestComparator.compare(valueToSearchFor, arrayToSearch.get(i)) == 0) {
System.out.println("element found in pos " + i + ". Returning true");
return true;
}
}
return false;
}
}
即使在找到真实结果并且所有期货都被取消后,我也可以从日志中看到线程仍在进行中
【问题讨论】:
标签: java multithreading parallel-processing executorservice callable