我正在创建一个简单的区块链应用程序,我有一个挖掘新区块的方法和一个可以提交挖掘任务的方法。
以下是我使用ExecutorService#submit
:提交新任务时使用的方法
public void executeCommand(int noOfStartingZero) throws ExecutionException, InterruptedException {
for (int i = 0; i < NO_OF_BLOCKS; i++) {
executor.submit(() -> {
Block prevBlock = this.blockchain.getBlocks().peekLast();
Block block = this.minerCommand.mine(prevBlock, noOfStartingZero);
System.out.println("block: " + block);
String minedBy = Thread.currentThread().getName();
block.setMinedBy(minedBy);
try {
this.blockchain.addNewBlock(block);
} catch (InvalidBlockException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
}
问题是,在这条线上,它总是返回相同的块:Block block = this.minerCommand.mine(prevBlock, noOfStartingZero);
这是我的mine()
方法,每次调用它都会创建一个新的块:
public Block mine(Block prevBlock, int noOfStartingZero) {
if (prevBlock == null) {
return getGenesisBlock(noOfStartingZero);
}
long startTime = System.currentTimeMillis();
var block = new Block();
block.setId(prevBlock.id() + 1);
block.setTimestamp(new Date().getTime());
block.setPrevHash(prevBlock.hash());
BlockHashContainer hashContainer = generateHash(block, noOfStartingZero);
block.setMagicNumber(hashContainer.getMagicNumber());
block.setHash(hashContainer.getHash());
block.setTimeGenerated((new Date().getTime() - startTime) / 1000);
return block;
}
我尝试打印出每次迭代的块,下面是我得到的,它总是返回第一个块,没有其他块添加到区块链中:
block: Block[id=1, timestamp=1632128365538, prevHash=0, hash=818b72956bdb163b5b51b848c2988378cb03bd58649511186ac9a5339d9e392c]
block: Block[id=1, timestamp=1632128365538, prevHash=0, hash=818b72956bdb163b5b51b848c2988378cb03bd58649511186ac9a5339d9e392c]
block: Block[id=1, timestamp=1632128365537, prevHash=0, hash=a840f8f7922fae5b974e1a4e286dbd7247ed19efb12629ba8b0533b117c9451d]
block: Block[id=1, timestamp=1632128365538, prevHash=0, hash=818b72956bdb163b5b51b848c2988378cb03bd58649511186ac9a5339d9e392c]
block: Block[id=1, timestamp=1632128365516, prevHash=0, hash=336385001bb8a9f7b16800fd94e09347dac1a2566bd0edfd0ea6c941b722dd4d]
为什么它会这样?任何帮助都将不胜感激。
使用ExecutorService
运行此操作可以同时运行每个迭代。这意味着在任何任务有机会设置prevBlock
之前,他们都可以将其视为null
。如果每次迭代都取决于上一次操作的结果,那么根本没有理由使用ExecutorService
。相反,在循环中同步运行每个挖掘操作。