0

I have this while loop in my code,

while(!this.hash.substring(0, difficulty).equals(offset)) {
    this.nonce++;
    this.hash = this.generateHash();
}

I need to run every iteration of this while loop in a new thread and making the overall task faster!!

I tried overriding the run() method of the Runnable interface as follows,

@Override
public void run() {
    while(!this.hash.substring(0, this.difficulty).equals(this.offset)) {
        this.nonce++;
        this.hash = this.generateHash();
    }
}

And running it like below,

ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
Runnable c = new Create(this.timestamp, this.transactions, this.previousHash, difficulty, offset)
es.execute(c);
es.shutdown();

But this does not seem to be working either!!

Is it possible?

Any answer would be great!! Thanks in advance!

-- EDIT --

Following is the full code and the while loop is inside the mineBlock() method.

public class Block {

    public static final String HASH_FN = "SHA-256";
    public static final String ENCODING = "UTF-8";
    
    private Date timestamp;
    private Transaction transaction;
    private String previousHash = "";
    private String hash;
    private Integer nonce = 0;  //random number, dynamic part

    public Block(Date timestamp, Transaction transaction) {
        super();
        this.timestamp = timestamp;
        this.transaction = transaction;
        hash = generateHash();
    }

    public String generateHash() {
                                                            //0, 1, 2  --> 000000000adf0991111111...64
        String base = this.timestamp + this.previousHash + this.nonce + this.transaction.toString();

        try {
            
            final MessageDigest digest = MessageDigest.getInstance(HASH_FN);
            final byte[] hash = digest.digest(base.getBytes(ENCODING));
            final StringBuilder hexString = new StringBuilder();

            for (int i = 0; i < hash.length; i++) {
                
                final String hex = Integer.toHexString(0xff & hash[i]);
                
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                
                hexString.append(hex);
            }
            
            return hexString.toString();
            
        } catch (Exception ex) {
            throw new RuntimeException("Hash Generation Exception");
        }
    }
    
    //[TODO]
    public void mineBlock(int difficulty) {
        
        String offset = String.join("", Collections.nCopies(difficulty, "0"));  //add leading 0
        
        while(!this.hash.substring(0, difficulty).equals(offset)) {
            this.nonce++;
            this.hash = this.generateHash();
        }
        
        System.out.println("A block mined!, hash " + this.hash);
    }

    public String getPreviousHash() {
        return previousHash;
    }
    
    public void setPreviousHash(String previousHash) {
        this.previousHash = previousHash;
    }

    public String getHash() {
        return hash;
    }
    
    public void setHash(String hash) {
        this.hash = hash;
    }

    @Override
    public String toString() {
        return "Block [timestamp=" + timestamp + ", transaction=" + transaction + ", previousHash="
                + previousHash + ", hash=" + hash + "]";
    }
    
    public void setFakeAmount(int fakeAmount) {
        this.transaction.setAmount(fakeAmount);
    }

}

-- EDIT 2 --

I used the following method since there are sharing resources. But, that method also does not seem to be working!!

BlockThread.java

public class BlockThread extends Thread {


    private Block block;

    public BlockThread(Block block) {
        this.block = block;
    }

    @Override
    public void run() {
        this.block.countNonce();
        this.block.genNewHash();
    }
}

Inside Block.java, I added the following methods to update corresponding variables.

public synchronized void countNonce() {
    this.nonce++;
}

public synchronized void genNewHash() {
    this.hash = this.generateHash();
}

Finally, I ran it like this (I took the mineBlock() method into another class where the blk is initialized with a new Block(...), and ran it from there. The non-parallel way works as expected in this design also.),

while(!blk.hash.substring(0, difficulty).equals(offset)) {
    Create create = new Create(blk);
    create.start();
}

When I'm viewing, nonce seems to be getting updated parallelly. But, the overall method does not work in multiple threads as expected!!

It would be great if anyone could help!!

  • Does this answer your question? [Java - creating a new thread](https://stackoverflow.com/questions/17758411/java-creating-a-new-thread) – Tibrogargan Apr 14 '22 at 19:59
  • Thanks for commenting!! I'm also new to threads and I don't really get how can I come up with a workaround for the mentioned while loop!! @Tibrogargan – Janitha Nawarathna Apr 14 '22 at 20:04
  • Even if you're using a ThreadPoolExecutor, which could parallelize the tasks submitted, you're just sending a single Runnable implementation. You're not performing any parallel execution. Maybe what you need is a ForkJoinPool if you could divide the hash generation in subsets. Try to edit your question and provide us with the generateHash() impementation. – Dan Apr 14 '22 at 20:05
  • You create a new thread by literally doing `myThread = new Thread ...; myThread.start()` (your code replaces the ellipsis). So ... create a class that inherits Thread and implement the run method, then just create as many as you want using new thread/start – Tibrogargan Apr 14 '22 at 20:08
  • @Tibrogargan, yes I have created a separate class that implements runnable and I have overridden the `run()` method as well!! , and @Dan I have updated the question including the full code! – Janitha Nawarathna Apr 15 '22 at 03:02
  • @Dan, here I ve updated the question again with another method that I used!! – Janitha Nawarathna Apr 15 '22 at 10:32

0 Answers0