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!!

janithahn
  • 141
  • 1
  • 8
  • 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 – janithahn 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! – janithahn Apr 15 '22 at 03:02
  • @Dan, here I ve updated the question again with another method that I used!! – janithahn Apr 15 '22 at 10:32

0 Answers0