我有一个 BigIntegers 的 HashMap (thisIsTheHashMapIAmSearchingThrough)。我有第二个 BigIntegers 的 HashMap,我试图将其值与第一个 HashMap 进行匹配,为了简化这篇文章的代码,我用随机生成的数字 (thisIsMyRandomBigIntegerIAmTryingToMatch) 替换了第二个 HashMap。但是,在进行匹配之前,我需要根据第三个 HashMap 中的数字执行一些数学运算。同样,我试图通过简单地使用一个递增 1 的数字来简化这篇文章,因为如果要找到匹配项,第三个 HashMap 中的数字必须增加。
现在,为了我的问题,这个数字并不重要,只要它变大,因为我问题中代码的重点不是真正找到匹配项(否则我会使用特定数字),而是增加同时操作的数量,这应该会加快我的实际程序找到匹配项所需的时间。我只是想通过实现多线程来最大化每秒的检查次数。我有原始的(虽然大大简化了)代码以及我尝试实现失败的多线程的简化版本。
这是我的原始代码的简化版本:
HashMap<Integer, BigInteger> thisIsTheHashMapIAmSearchingThrough = new HashMap<Integer, BigInteger>();
int thisIsTheNumberOfElementsInTheHashMapIAmSearchingThrough = 100000;
int thisIsTheMaximumNumberOfBitsUsedForTheRandomBigIntegersInMyHashMap = 500;
for (int thisIsTheIntToIncrimentThroughMyHashMap = 1; thisIsTheIntToIncrimentThroughMyHashMap <= thisIsTheNumberOfElementsInTheHashMapIAmSearchingThrough; thisIsTheIntToIncrimentThroughMyHashMap++) {
thisIsTheHashMapIAmSearchingThrough.put(i, new BigInteger(thisIsTheMaximumNumberOfBitsUsedForTheRandomBigIntegersInMyHashMap, new Random()));
}
BigInteger thisIsTheMaximumValueOneOfMyRandomBigIntegersCouldBe = BigInteger.TWO.pow(thisIsTheMaximumNumberOfBitsUsedForMyRandomBigIntegersInMyHashMap);
boolean thisIsTheBooleanToStoreWhetherMyNumberIsFound = false;
BigInteger thisIsTheNumberThatIAmUsingToDivideBy;
int thisIsTheMaximumNumberOfBitsUsedForMyRandomBigIntegerIAmTryingToMatch = 100;
BigInteger thisIsMyRandomBigIntegerIAmTryingToMatch = new BigInteger(thisIsTheMaximumNumberOfBitsUsedForMyRandomBigIntegerIAmTryingToMatch, new Random());
for (thisIsTheNumberThatIAmUsingToDivideBy = BigInteger.TWO; thisIsTheNumberThatIAmUsingToDivideBy.compareTo(thisIsTheMaximumValueOneOfMyRandomBigIntegersCouldBe) < 0; thisIsTheNumberThatIAmUsingToDivideBy = thisIsTheNumberThatIAmUsingToDivideBy.add(BigInteger.ONE)) {
for (int thisIsAnotherIntToIncrimentThroughMyHashMap = 1; thisIsAnotherIntToIncrimentThroughMyHashMap <= thisIsTheNumberOfElementsInTheHashMapIAmSearchingThrough; thisIsAnotherIntToIncrimentThroughMyHashMap++) {
BigInteger thisIsABigIntegerToStoreTheReturnedValueForTheKeyProvided = toSearch.get(thisIsAnotherIntToIncrimentThroughMyHashMap);
thisIsABigIntegerToStoreTheReturnedValueForTheKeyProvided = thisIsABigIntegerToStoreTheReturnedValueForTheKeyProvided .divide(thisIsTheNumberThatIAmUsingToDivideBy);
if (thisIsABigIntegerToStoreTheReturnedValueForTheKeyProvided .compareTo(thisIsMyRandomBigIntegerIAmTryingToMatch) == 0) {
thisIsTheBooleanToStoreWhetherMyNumberIsFound = true;
break;
}
}
if (thisIsTheBooleanToStoreWhetherMyNumberIsFound) { thisIsTheMaximumNumberOfBitsUsedForMyRandomBigIntegerIAmTryingToMatch --;
if (thisIsTheMaximumNumberOfBitsUsedForMyRandomBigIntegerIAmTryingToMatch < 10) {
break;
}
thisIsMyRandomBigIntegerIAmTryingToMatch = new BigInteger(thisIsTheMaximumNumberOfBitsUsedForMyRandomBigIntegerIAmTryingToMatch, new Random());
thisIsTheNumberThatIAmUsingToDivideBy = BigInteger.TWO;
}
}
现在,这是我尝试实现多线程的简化代码:
HashMap<Integer, BigInteger> thisIsTheHashMapIAmSearchingThrough = new HashMap<Integer, BigInteger>();
int thisIsTheNumberOfElementsInMyHashMap = 100000;
int thisIsTheMaximumNumberOfBitsAllowedInTheRandomlyGeneratedBigIntegersInMyHashMap = 500;
for (int thisIsTheIntUsedToIncrementThroughMyHashMap = 1; thisIsTheIntUsedToIncrementThroughMyHashMap <= thisIsTheNumberOfElementsInMyHashMap; thisIsTheIntUsedToIncrementThroughMyHashMap++) {
thisIsTheHashMapIAmSearchingThrough.put(thisIsTheIntUsedToIncrementThroughMyHashMap, new BigInteger(thisIsTheMaximumNumberOfBitsAllowedInTheRandomlyGeneratedBigIntegersInMyHashMap, new Random()));
}
BigInteger thisIsTheHighesPossibleValueOfARandomlyGeneratedBigIntegerInMyHashMap = BigInteger.TWO.pow(thisIsTheMaximumNumberOfBitsAllowedInTheRandomlyGeneratedBigIntegersInMyHashMap).subtract(BigInteger.ONE);
BigInteger thisIsTheNumberIAmDividingBy;
int thisIsTheMaximumNumberOfBitsAllowedInTheRandomlyGeneratedBigIntegerIAmTryingToMatch = 100;
BigInteger thisIsTheNumberIAmTryingToMatch = new BigInteger(thisIsTheMaximumNumberOfBitsAllowedInTheRandomlyGeneratedBigIntegerIAmTryingToMatch, new Random());
for (thisIsTheNumberIAmDividingBy = BigInteger.TWO; thisIsTheNumberIAmDividingBy.compareTo(thisIsTheHighesPossibleValueOfARandomlyGeneratedBigIntegerInMyHashMap) < 0;) {
ExecutorService thisIsMyExecutorService = Executors.newFixedThreadPool(1);
CompletionService<BigInteger>
thisIsMyExecutorCompletionService = new ExecutorCompletionService<BigInteger>(thisIsMyExecutorService);
List<GetBi> thisIsAListOfMyCallableBigIntegerClassGetBi = new ArrayList<>();
for (int thisIsTheIntUsedToTrackAddingToMyListAHundredInstancesAtATime = 1; thisIsTheIntUsedToTrackAddingToMyListAHundredInstancesAtATime <= 100; thisIsTheIntUsedToTrackAddingToMyListAHundredInstancesAtATime++) {
thisIsAListOfMyCallableBigIntegerClassGetBi.add(new GetBi(thisIsTheIntUsedToTrackAddingToMyListAHundredInstancesAtATime, thisIsTheHashMapIAmSearchingThrough, thisIsTheNumberIAmDividingBy = thisIsTheNumberIAmDividingBy.add(BigInteger.ONE), thisIsTheNumberIAmTryingToMatch));
}
for (GetBi thisIsASingleInstanceOfMyListOfCallableBigIntegerClasses : thisIsAListOfMyCallableBigIntegerClassGetBi) {
thisIsMyExecutorCompletionService.submit(thisIsASingleInstanceOfMyListOfCallableBigIntegerClasses);
}
thisIsMyExecutorService.shutdown();
try {
while (!thisIsMyExecutorService.isTerminated()) {
final Future<BigInteger> thisIsAFutureToHoldTheValueReturnedFromMyBigIntegerCallableWhenThreadsFinish = thisIsMyExecutorCompletionService.take();
if (thisIsAFutureToHoldTheValueReturnedFromMyBigIntegerCallableWhenThreadsFinish.get().compareTo(BigInteger.ZERO) > 0) {
thisIsMyExecutorService.shutdownNow();
thisIsTheMaximumNumberOfBitsAllowedInTheRandomlyGeneratedBigIntegerIAmTryingToMatch--;
if (thisIsTheMaximumNumberOfBitsAllowedInTheRandomlyGeneratedBigIntegerIAmTryingToMatch < 10) {
break;
}
thisIsTheNumberIAmTryingToMatch = new BigInteger(thisIsTheMaximumNumberOfBitsAllowedInTheRandomlyGeneratedBigIntegerIAmTryingToMatch, new Random());
thisIsTheNumberIAmDividingBy = BigInteger.TWO;
}
}
} catch (InterruptedException | ExecutionException thisIsTheNameOfAnException) {
thisIsTheNameOfAnException.printStackTrace();
} finally {
thisIsMyExecutorService.shutdownNow();
}
}
这是 BigInteger 的类:
public class GetBi implements Callable<BigInteger> {
private final int thisIsTheNumberOfElementsInMyHashMap;
private final HashMap<Integer, BigInteger> thisIsTheHashMapIAmSearchingThrough;
private final BigInteger thisIsTheNumberIAmGoingToDivideBy;
private final BigInteger thisIsTheNumberIAmTryingToFindAMathFor;
public GetBi(int thisIsTheNumberOfElementsInMyHashMap, HashMap<Integer, BigInteger> thisIsTheHashMapIAmSearchingThrough, BigInteger thisIsTheNumberIAmGoingToDivideBy, BigInteger thisIsTheNumberIAmTryingToFindAMathFor) {
this.thisIsTheNumberOfElementsInMyHashMap = thisIsTheNumberOfElementsInMyHashMap;
this.thisIsTheHashMapIAmSearchingThrough = thisIsTheHashMapIAmSearchingThrough;
this.thisIsTheNumberIAmGoingToDivideBy = thisIsTheNumberIAmGoingToDivideBy;
this.thisIsTheNumberIAmTryingToFindAMathFor = thisIsTheNumberIAmTryingToFindAMathFor;
}
@Override
public BigInteger call() throws Exception {
ExecutorService thisIsTheExecutorServiceUsedByThisClass = Executors.newFixedThreadPool(1);
CompletionService<Boolean> thisIsTheExecutorCompletionServiceUsedByThisClass = new ExecutorCompletionService<Boolean>(thisIsTheExecutorServiceUsedByThisClass);
List<GetBool> thisIsTheListToStoreMyCallableBooleanClassGetBool = new ArrayList<>();
for (int i = 1; i <= thisIsTheNumberOfElementsInMyHashMap; i++) {
thisIsTheListToStoreMyCallableBooleanClassGetBool.add(new GetBool(i, thisIsTheHashMapIAmSearchingThrough, thisIsTheNumberIAmGoingToDivideBy, thisIsTheNumberIAmTryingToFindAMathFor));
}
for (GetBool thisIsASingleElementOfMyListOfCallableBooleanClasses : thisIsTheListToStoreMyCallableBooleanClassGetBool) {
thisIsTheExecutorCompletionServiceUsedByThisClass.submit(thisIsASingleElementOfMyListOfCallableBooleanClasses);
}
thisIsTheExecutorServiceUsedByThisClass.shutdown();
try {
while (!thisIsTheExecutorServiceUsedByThisClass.isTerminated()) {
final Future<Boolean> thisIsAFutureToStoreTheReturnedBooleansAsThreadsFinishThem = thisIsTheExecutorCompletionServiceUsedByThisClass.take();
if (thisIsAFutureToStoreTheReturnedBooleansAsThreadsFinishThem.get()) {
thisIsTheExecutorServiceUsedByThisClass.shutdownNow();
return thisIsTheNumberIAmGoingToDivideBy;
}
}
} finally {
thisIsTheExecutorServiceUsedByThisClass.shutdownNow();
}
return BigInteger.ZERO;
}
}
这里是布尔值:
public class GetBool implements Callable<Boolean> {
private final int thisIsTheCurrentKeyUsedToReturnAValueFromMyHashMap;
private final HashMap<Integer, BigInteger> thisIsTheHashMapIAmSearchingThrough;
private final BigInteger thisIsTheNumberIAmGoingToDivideBy;
private final BigInteger thisIsTheNumberIAmTryingToMatch;
public GetBool(int thisIsTheNumberIAmTryingToFindAMathFor, HashMap<Integer, BigInteger> thisIsTheHashMapIAmSearchingThrough, BigInteger thisIsTheNumberIAmGoingToDivideBy, BigInteger thisIsTheNumberIAmTryingToMatch) {
this.thisIsTheCurrentKeyUsedToReturnAValueFromMyHashMap = thisIsTheNumberIAmTryingToFindAMathFor;
this.thisIsTheHashMapIAmSearchingThrough = thisIsTheHashMapIAmSearchingThrough;
this.thisIsTheNumberIAmGoingToDivideBy = thisIsTheNumberIAmGoingToDivideBy;
this.thisIsTheNumberIAmTryingToMatch = thisIsTheNumberIAmTryingToMatch;
}
@Override
public Boolean call() throws Exception {
BigInteger thisIsTheResultIAmCheckingAgainstTheNumberIAmTryingToMatch = thisIsTheHashMapIAmSearchingThrough.get(thisIsTheCurrentKeyUsedToReturnAValueFromMyHashMap).divide(thisIsTheNumberIAmGoingToDivideBy);
if (thisIsTheResultIAmCheckingAgainstTheNumberIAmTryingToMatch.compareTo(thisIsTheNumberIAmTryingToMatch) == 0)
{
return Boolean.TRUE;
}
else
{
return Boolean.FALSE;
}
}
}
这就是我在尝试实现多线程时想出的方法,它可以在不需要让每个线程都完成的情况下停止。我的代码有问题,因为即使每个池中有 1 个线程,它仍然会失败。多线程版本和原始版本应该大约同时运行,每个池只有 1 个线程。然而,几秒钟后,该应用程序继续运行而没有做任何事情并且不再到达我提供的代码中的任何行,而是迷失在 Java 的内部代码中,这些代码被故意隐藏以避免程序员破坏他们的整个 Java 语言,而不是只是他们的特定程序。这不是线程过多或内存过多的问题,因为我仍然可以切换断点并且 IDE 不会崩溃。我的代码似乎在一两个循环后停止运行。非常感谢任何帮助我的多线程尝试成功的帮助。