【发布时间】:2015-11-15 01:15:33
【问题描述】:
我正在尝试计算一些大数字。为了加快计算速度,我想使用多线程。每个线程应该计算一个数字,最后计算一个总和。
我曾经看到与SumThread 和Collector 一起使用的东西,如下所示:
public BigInteger compute(int p) {
Collector c = new Collector(p);
for(T element : Collection<T> bigCollection) {
new SumThread(c) {
@Override
protected void doTheJob() {
long big = someVeryComplexCalculation(element, ...); //n!
receive(BigInteger.valueOf(big));
}
}
}
if(collector.isReady())
return collector.getResult();
return null;
}
public class Collector {
private int numberOfProcesses;
private int numberOfAllowedProcesses;
private BigInteger result;
public Collector(int n) {
numberOfAllowedProcesses = n;
numberOfProcesses = 0;
result = BigInteger.ZERO;
}
synchronized public void enter() throws InterruptedException {
if (numberOfProcesses == numberOfAllowedProcesses) wait();
numberOfProcesses++;
}
synchronized public void leave() {
numberOfProcesses--;
notify();
}
synchronized public void register(BigInteger v) {
result = result.add(v);
}
synchronized public boolean isReady() throws InterruptedException {
while (numberOfProcesses > 0) wait();
return true;
}
...
}
public abstract class SumThread extends Thread {
private Collector collector;
public SumThread(Collector c) throws InterruptedException {
collector = c;
collector.enter();
}
abstract protected void doTheJob(); //complex calculations can be done in here
public void receive(BigInteger t) {
collector.register(t);
}
public void run() {
doTheJob();
collector.leave();
}
}
我认为我可以通过使用ExecutorService 而不是不断创建新的Threads 来轻松超越这一点:
public BigInteger compute(int p) {
ExecutorService pool = Executors.newFixedThreadPool(p);
Future<BigInteger>[] futures = new Future<BigInteger>[bigCollection.size()];
int i = 0;
for(T element : Collection<T> bigCollection) {
futures[i++] = p.submit(new Callable<BigInteger>() {
@Override
public BigInteger call() {
long big = someVeryComplexCalculation(element, ...); //n!
return BigInteger.valueOf(big);
}
}
}
// or with ExecutorCompletionService, but the loop remains I guess
BigInteger res = BigInteger.ZERO
for(Future<BigInteger> f : futures)
res = res.add(f.get());
return res;
}
但是,此代码的性能并没有优于 SumThread-Collector 解决方案。例如,我也看到了关于 LongAdder 的事情,但我需要一些 BigIntegers 的加法器......
因此,我的问题是:同时计算总和的最佳方法是什么?是上述方法之一还是有完全不同(但更好)的方法?
【问题讨论】:
标签: java multithreading concurrency parallel-processing biginteger