Как периодически печатать на терминал из оператора if, который вложен в цикл while (Java) - PullRequest
1 голос
/ 06 апреля 2019

Я пишу Java-приложение, которое будет хэшировать серию входных значений несколько раз, пока не будет выполнено условие. Я достиг этого, вложив ряд операторов if / else в цикл while. Я хочу, чтобы можно было печатать скорость хэширования на терминал каждые 3 секунды, пока приложение активно хэширует, и не повторно, пока не будет выполнено условие. Я пытался использовать ExecutorService и планировать TimerTask, но ни один из них не работал так, как я хотел, чтобы они оба продолжали выполняться после выполнения условия, которое должно было их остановить. Я знаю, что что-то упустил, но не знаю что):

Я включил небольшой фрагмент, не стесняйтесь спрашивать любую информацию, которая может показаться вам актуальной.

Любая помощь будет принята с благодарностью!

Я пытался использовать 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;
        }
    }
}  

РЕДАКТИРОВАТЬ: То, что это будет, когда закончено, по сути, является дрянной «цепочкой блоков», которую я буду использовать для иллюстративных целей в качестве учебного пособия, имея в виду, что я включил остальную часть метода «майнера» ниже:

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) {

            ...........

Все параметры, которые принимает метод 'miner', передаются ему классом запуска, который включает в себя функцию main. Моя цель состоит в том, чтобы иметь возможность печатать скорость хэширования при поиске «действительного» хеша каждые несколько секунд вместо того, чтобы печатать тысячи раз в секунду.

Ответы [ 2 ]

1 голос
/ 06 апреля 2019

У меня есть несколько предложений:

  • Лично я предпочел бы использовать break внутри цикла while(true) вместо переменной цикла. Я чувствую, что это делает код более читабельным;

  • Вы объявляете Timer внутри цикла, что означает, что новый таймер создается на каждой итерации цикла. Вам нужно создать таймер один раз, вне цикла.

Переменная Timer должна быть конечной, чтобы можно было вызывать timer.cancel() внутри функции запуска TimerTask. Если вы планируете завершить таймер за пределами функции запуска, переменная 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;
            }
        }  
    }
}

Пожалуйста, дайте мне знать, если вам нужна помощь.


Edit:

Несколько вещей, которые я заметил:

  • Переменная класса Nonce не может быть статической, в противном случае она будет использоваться всеми экземплярами класса.

  • Имя переменной не может быть Nonce в объявлении функции, в противном случае локальная копия будет использоваться всякий раз, когда вы используете Nonce в функции майнера.

  • Если вы не рассчитываете hashRate напрямую, тогда deltaS может быть нулевым, что может привести к ошибке деления на 0.

Пожалуйста, дайте мне знать, если вам нужны какие-либо разъяснения.

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();
.......
0 голосов
/ 06 апреля 2019

Хорошо, для меня сработало объявление статических переменных, начало цикла таймера перед циклом и отмена при обнаружении действительного хеша, например:

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();
.......
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...