实现多线程以在 HashMap 中查找任何匹配项;找到第一个匹配时终止其他线程

问题描述 投票:0回答:0

这是我原始代码的简化版本:

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 不会崩溃,我的代码似乎只是在一两个循环后停止运行。非常感谢任何帮助我的多线程尝试成功的帮助。

java multithreading threadpool executor
© www.soinside.com 2019 - 2024. All rights reserved.