Home > OS >  Value inside submitted task always the same - ExecutorService
Value inside submitted task always the same - ExecutorService

Time:09-21

I'm creating a simple blockchain application, I have a method for mining new blocks and a method where I can submit mining tasks.

Here is the method that I use for submitting new tasks using 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();
 }

The problem is, on this line, it always returns the same block: Block block = this.minerCommand.mine(prevBlock, noOfStartingZero);

Here is my mine() method, each time it gets called it will create a new block:

 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;
 }

I tried to print out the block for each iteration, and here is what I got, it always returns the first block, and no other block is added to the blockchain:

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]

Why it behaves like this? Any help would be much appreciated.

CodePudding user response:

Using an ExecutorService to run this operation has the potential to run each iteration concurrently. This means that they can all see prevBlock as null before any task has the opportunity to set it. If each iteration depends on the result of the previous operation, there’s no reason to use an ExecutorService at all. Instead, run each mining operation synchronously within the loop.

  • Related