简体   繁体   English

如何从嵌套在 while 循环中的 if 语句定期打印到终端(Java)

[英]How to periodically print to terminal from an if statement that is nested in a while loop (Java)

I am writing a java application that will hash a series of input values repeatedly until a condition is met.我正在编写一个 java 应用程序,它将重复散列一系列输入值,直到满足条件。 I have accomplished this by nesting a series of if/else statements inside a while loop.我通过在 while 循环中嵌套一系列 if/else 语句来实现这一点。 I want to be able to print the hash rate to the terminal every 3 seconds while the application is actively hashing, and not repeatedly until the condition is met.我希望能够在应用程序主动散列时每 3 秒将散列率打印到终端,并且在满足条件之前不会重复打印。 I have tried using ExecutorService and scheduling a TimerTask but neither worked the way I wanted them to as they both kept on executing after the condition that should have stopped them was met.我曾尝试使用 ExecutorService 并安排 TimerTask 但都没有按照我希望的方式工作,因为在满足应该停止它们的条件之后它们都继续执行。 I know I am missing something but I don't know what ):我知道我错过了一些东西,但我不知道是什么):

I've included a small snippet, feel free to ask for any information you may think is relevant.我已经包含了一个小片段,请随时询问您认为相关的任何信息。

Any help would be greatly appreciated!任何帮助将不胜感激!

I tried using a TimerTask like this:我尝试使用这样的 TimerTask:

while(iterator) {
    if (difficulty == 1) {
        if (!hash.startsWith("0")) {
            long updatedTime = System.nanoTime();
            Nonce++;
            long deltaN = updatedTime - startTime;
            long deltaS = (deltaN / 1000000000);
            long hashRate = (Nonce / deltaS);
            Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    System.out.println("Current hash rate: " + hashRate + " " + "hash/s");
                }
            }, 0, 3000);
        } else {
              System.out.println("Valid hash found! " + hash);
              iterator = false;
        }
    }
}  

EDIT: What this will be when finished is essentially a cheesy 'block chain' I will be using for illustrative purposes as a teaching tool, with that in mind I have included the rest of the 'miner' method below:编辑:完成后这基本上是一个俗气的“区块链”,我将用作说明目的作为教学工具,考虑到这一点,我已经包括了下面的“矿工”方法的其余部分:

public void miner(long index, long currentTimeMillis, long data, long Nonce, String previousBlockHash, int difficulty) throws InterruptedException {
        this.index = index;
        this.currentTimeMillis = currentTimeMillis;
        this.pszTimeStamp = pszTimeStamp;
        this.Nonce = Nonce;
        this.previousBlockHash = previousBlockHash;
        this.difficulty = difficulty;
        this.data = data;
        boolean iterator = true;
        String blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
        String hash = SHA256.generateHash(blockHeader);
        long startTime = System.nanoTime();
        TimeUnit.SECONDS.sleep(2);

        while (iterator) {
            blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
            hash = SHA256.generateHash(blockHeader);
            if (difficulty == 1) {
                if (!hash.startsWith("0")) {
                    long updatedTime = System.nanoTime();
                    Nonce++;
                    long deltaN = updatedTime - startTime;
                    long deltaS = (deltaN / 1000000000);
                    long hashRate = (Nonce / deltaS);
                    System.out.println("Current hash rate: " + hashRate
                } else {
                    System.out.println("\n");
                    System.out.println("Hash found! \n");
                    System.out.println("Mined block hash: \n" + hash);
                }
            } else if (difficulty == 2) {

            ...........

All of the parameters the 'miner' method takes are passed to it by a launching class which includes the main function. 'miner' 方法采用的所有参数都由包含 main 函数的启动类传递给它。 My goal is to be able to print the hash rate while it searches for a 'valid' hash every few seconds instead of it printing thousands of times per second.我的目标是能够在每隔几秒搜索“有效”哈希时打印哈希率,而不是每秒打印数千次。

I have a few suggestions:我有几点建议:

  • I personally would prefer using break inside a while(true) loop instead of of a loop variable.我个人更喜欢在while(true)循环中使用break while(true)不是循环变量。 I feel that it makes the code more readable;我觉得它使代码更具可读性;

  • You are re declaring the Timer inside the loop, which means that a new timer is created each iteration of the loop.您正在循环内重新声明Timer ,这意味着每次循环迭代都会创建一个新计时器。 You need to create the timer once, outside the loop.您需要在循环之外创建一次计时器。

The Timer variable needs to be final to allow you to call timer.cancel() inside the run function of the TimerTask. Timer变量需要是最终的,以允许您在 TimerTask 的运行函数中调用timer.cancel() If you plan on terminating the timer outside the run function, then the Timer variable need not be final.如果您计划在 run 函数之外终止计时器,则Timer变量不必是最终的。

import java.util.*;

public class Test{
    static double Nonce;

    public static void main(String... args) throws Exception{
        final Timer timer = new Timer();
        timer.schedule(new TimerTask(){
            public void run(){
                //calcualte hashRate by any formula
                double hashRate = Nonce/100.0;

                //check if the timer needs to continue, else call timer.cancel()

                System.out.println(hashRate);
            }
        }, 0, 500);

        while(true){
            Thread.sleep(100);
            Nonce++;

            if(Nonce == 100){
                timer.cancel(); //or terminate the timer outside the loop
                break;
            }
        }  
    }
}

Please let me know if you need any help.如果您需要任何帮助,请告诉我。


Edit:编辑:

A few things I have noticed:我注意到了一些事情:

  • The class variable Nonce cannot be static, otherwise it will be shared amongst all instances of the class.类变量Nonce不能是静态的,否则它将在类的所有实例之间共享。

  • The name of the variable cannot be Nonce in the function declaration, otherwise the local copy will be used whenever you use Nonce within the miner function.变量名在函数声明中不能是Nonce ,否则无论何时在miner函数中使用Nonce都会使用本地副本。

  • If you do not calculate the hashRate directly, then deltaS can be zero, which may lead to a divide by 0 error.如果不直接计算 hashRate,则 deltaS 可能为零,这可能会导致除以 0 的错误。

Please let me know if you need any clarification.如果您需要任何说明,请告诉我。

public class ChainBuilder extends MainChain {

    private long index;
    private long currentTimeMillis;
    private long data;
    private int difficulty;
    private String pszTimeStamp;
    private String previousBlockHash;
    private String currentHash;
    private String genesisHash;

    public long Nonce; //Nonce cannot be be static, otherwise it will cause issues if more than one object is created.
    public static long startTime;

.......
public void miner(long index, long currentTimeMillis, long data, long _Nonce /*You cannot use Nonce here*/, String previousBlockHash, int difficulty) throws InterruptedException {
        this.index = index;
        this.currentTimeMillis = currentTimeMillis;
        this.pszTimeStamp = pszTimeStamp;
        this.Nonce = _Nonce; /*In this scope, Nonce refers to the local variable, and this.Nonce refers to the class variable. 
                            If you use Nonce in this scope, then the class variable will not be changed.*/
        this.previousBlockHash = previousBlockHash;
        this.difficulty = difficulty;
        this.data = data;
        boolean iterator = true;
        String blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
        String hash = SHA256.generateHash(blockHeader);
        startTime = System.nanoTime();
        TimeUnit.SECONDS.sleep(2);

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                long endTime = System.nanoTime();
                long deltaN = endTime - startTime;
                //long deltaS = (deltaN / 1_000_000_000);
                long hashRate = (1_000_000_000 * Nonce / deltaN); /*calculate the hashRate directly, because if deltaN < 1_000_000_000, 
                                                                then deltaS will be 0, giving a divide by zero error.*/
                System.out.println("Current hash rate: " + hashRate + " " + "hash/s");
            }
        }, 0, 3000);
        while (iterator) {
            blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
            hash = SHA256.generateHash(blockHeader);
            if (difficulty == 1) {

                if (!hash.startsWith("0")) {
                    Nonce++;
                } else {
                    System.out.println("Hash found!");
                    timer.cancel();
.......

Okay, so what worked for me was declaring the relevant variables static, putting the start of the timer before loop, and cancelling upon the discovery of a valid hash, like so:好的,所以对我有用的是将相关变量声明为静态,将计时器的开始置于循环之前,并在发现有效散列时取消,如下所示:

public class ChainBuilder extends MainChain {

    private long index;
    private long currentTimeMillis;
    private long data;
    private int difficulty;
    private String pszTimeStamp;
    private String previousBlockHash;
    private String currentHash;
    private String genesisHash;
    public static long deltaS;
    public static long deltaN;
    public static long Nonce;
    public static long startTime;
    public static long endTime;
    public static long hashRate;
.......
public void miner(long index, long currentTimeMillis, long data, long Nonce, String previousBlockHash, int difficulty) throws InterruptedException {
        this.index = index;
        this.currentTimeMillis = currentTimeMillis;
        this.pszTimeStamp = pszTimeStamp;
        this.Nonce = Nonce;
        this.previousBlockHash = previousBlockHash;
        this.difficulty = difficulty;
        this.data = data;
        boolean iterator = true;
        String blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
        String hash = SHA256.generateHash(blockHeader);
        startTime = System.nanoTime();
        TimeUnit.SECONDS.sleep(2);

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("Current hash rate: " + hashRate + " " + "hash/s");
            }
        }, 0, 3000);
        while (iterator) {
            blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
            hash = SHA256.generateHash(blockHeader);
            if (difficulty == 1) {

                if (!hash.startsWith("0")) {
                    endTime = System.nanoTime();
                    Nonce++;
                    deltaN = endTime - startTime;
                    deltaS = (deltaN / 1000000000);
                    hashRate = (Nonce / deltaS);
                } else {
                    System.out.println("Hash found!");
                    timer.cancel();
.......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM