这是我原始代码的简化版本:
HashMap<Integer, BigInteger> toSearch = new HashMap<Integer, BigInteger>();
int tsSize = 100000;
int maxLen = 500;
for (int i = 1; i <= tsSize; i++) {
toSearch.put(i, new BigInteger(maxLen, new Random()));
}
BigInteger maxSearchable = BigInteger.TWO;
maxSearchable = maxSearchable.pow(maxLen);
boolean found = false;
BigInteger toDivide;
int mnLen = 100;
BigInteger myNumber = new BigInteger(mnLen, new Random());
for (toDivide = BigInteger.TWO; toDivide.compareTo(maxSearchable) < 0; toDivide = toDivide.add(BigInteger.ONE)) {
for (int i = 1; i <= tsSize; i++) {
BigInteger bi = toSearch.get(i);
BigInteger result = bi.divide(toDivide);
if (result.compareTo(myNumber) == 0) {
found = true;
break;
}
}
if (found) {
mnLen--;
if (mnLen < 10) {
break;
}
myNumber = new BigInteger(mnLen, new Random());
toDivide = BigInteger.TWO;
}
}
现在,这是我尝试实现多线程的简化代码:
for (toDivide = BigInteger.TWO; toDivide.compareTo(maxSearchable) < 0; toDivide = toDivide.add(BigInteger.ONE)) {
ExecutorService es = Executors.newFixedThreadPool(1);
CompletionService<BigInteger> cs = new ExecutorCompletionService<BigInteger>(es);
List<GetBi> biList = new ArrayList<>();
for (int i = 1; i <= 100; i++) {
biList.add(new GetBi(i, toSearch, toDivide, myNumber));
}
for (GetBi gb : biList) {
cs.submit(gb);
}
es.shutdown();
try {
while (!es.isTerminated()) {
final Future<BigInteger> future = cs.take();
if (future.get().compareTo(BigInteger.ZERO) > 0) {
es.shutdownNow();
mnLen--;
if (mnLen < 10)
{
break;
}
myNumber = new BigInteger(mnLen, new Random());
toDivide = BigInteger.TWO;
}
}
} catch (InterruptedException | ExecutionException e1) {
e1.printStackTrace();
} finally {
es.shutdownNow();
}
}
这是 BigInteger 的类:
public class GetBi implements Callable<BigInteger> {
private final int tsSize;
private final HashMap<Integer, BigInteger> ts;
private final BigInteger td;
private final BigInteger mn;
public GetBi(int tsSize, HashMap<Integer, BigInteger> toSearch, BigInteger toDivide, BigInteger myNumber) {
this.tsSize = tsSize;
this.ts = toSearch;
this.td = toDivide;
this.mn = myNumber;
}
@Override
public BigInteger call() throws Exception {
ExecutorService es = Executors.newFixedThreadPool(1);
CompletionService<Boolean> cs = new ExecutorCompletionService<Boolean>(es);
List<GetBool> bList = new ArrayList<>();
for (int i = 1; i <= tsSize; i++) {
bList.add(new GetBool(i, ts, td, mn));
}
for (GetBool gb : bList) {
cs.submit(gb);
}
es.shutdown();
try {
while (!es.isTerminated()) {
final Future<Boolean> future = cs.take();
if (future.get()) {
es.shutdownNow();
return td;
}
}
} finally {
es.shutdownNow();
}
return BigInteger.ZERO;
}
}
这里是布尔值:
public class GetBool implements Callable<Boolean> {
private final int key;
private final HashMap<Integer, BigInteger> ts;
private final BigInteger td;
private final BigInteger mn;
public GetBool(int key, HashMap<Integer, BigInteger> ts, BigInteger td, BigInteger mn) {
this.key = key;
this.ts = ts;
this.td = td;
this.mn = mn;
}
@Override
public Boolean call() throws Exception {
BigInteger bi = ts.get(key);
BigInteger result = bi.divide(td);
if (result.compareTo(mn) == 0) {
return Boolean.TRUE;
} else {
return Boolean.FALSE;
}
}
}
这就是我在尝试实现多线程时想出的方法,它可以在不需要让每个线程都完成的情况下停止。我的代码有问题,因为即使每个池中有 1 个线程,它仍然会失败。多线程版本和原始版本应该大约同时运行,每个池只有 1 个线程。然而,几秒钟后,整体继续运行,什么也没做。它只是冻结在我编写的任何代码中都不存在的某行代码上。这不是线程太多或使用太多内存的问题,因为我仍然可以切换断点并且 IDE 不会崩溃,我的代码似乎只是在一两个循环后停止运行。非常感谢任何帮助我的多线程尝试成功的帮助。