如何重新启动计时器倒计时

问题描述 投票:0回答:2

我正在尝试重置计时器,以便它可以从我的数组中提取另一个值。 有谁知道解决方案吗?我的错误是:

peat = peat= 1; 
local variables referenced from an inner class must be final or effectively final

我被困住了,我知道我需要重置计时器,但我不知道如何操作。

class MyProgram {

    public static void main(String[] args) {
        int peat = 0;
        int cdown = 0;
        Scanner input1 = new Scanner(System.in);
        System.out.println("What is your name");
        String personsName = input1.next();
        System.out.println((personsName) + " Are you ready to impove yourself");
        String motiv = input1.next();

        String[] myArray = new String[4];
        myArray[0] = "Keep going";
        myArray[1] = "1 more rep";
        myArray[2] = "you have come so far don't stop now";
        myArray[3] = "Think of the progress you have made";

        if (motiv.equals("yes")) {
            System.out.println("Today is the day hard work begins");
        } else {
            System.out.println("type yes when you're ready to work");
        }

        Scanner input2 = new Scanner(System.in);
        System.out.println("You will recive quotes throughout your workout to remind you to keep working type ok if you accept");
        String confirm = input2.next();

        if (confirm.equals("ok")) {
            final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
            final Runnable runnable = new Runnable() {
                int countdown = 10;
                public void run() {
                    System.out.println(countdown);
                    countdown--;
                    if (countdown == 0 && peat < 4) {
                        System.out.println(myArray[0]);
                        //reset count down to 10
                        peat = peat + 1;
                    } else {
                        scheduler.shutdown();
                    }
                }
            };
            scheduler.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.SECONDS);
        }
        while (cdown < 1) {
            System.out.println(myArray[1]);
            cdown = cdown + 1;
        }
    }
}
java multithreading executorservice anonymous-class scheduledexecutorservice
2个回答
1
投票

正如错误消息所述,Java 不允许在“lambda”作用域内修改属于外部作用域的变量(匿名类的实例也会创建这样的作用域)。

在您的情况下,为了解决此问题,您可以将

peat
设为类变量:

import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;
import static java.util.concurrent.TimeUnit.SECONDS;

public class MyProgram {

    private static int peat = 0;

    public static void main(String[] args) {
        // Code of main()
        // Remove local "peat" variable
    }
}

1
投票

这是因为

peat
不是最终变量或有效最终变量。正如文档所述:

匿名类无法访问其封闭范围内未声明为final或有效final的局部变量。

当匿名类访问封闭块的局部变量时,匿名类捕获该变量。这意味着变量的值实际上是在匿名类中复制的。

在您的例子中,您使用 lambda 表达式来提供

Runnable
的实现。与匿名类一样,lambda 表达式被称为“词法作用域”,这意味着它们不会引入任何新级别的作用域。此外,它们也可以从封闭范围捕获变量。

与本地类和匿名类一样,lambda 表达式可以捕获变量;它们对封闭范围的局部变量具有相同的访问权限。 [...] Lambda 表达式具有词法范围。这意味着它们不会从超类型继承任何名称或引入新级别的范围。

与本地类和匿名类一样,lambda 表达式只能访问封闭块的本地变量和参数,这些变量和参数是
final

有效地final

虽然匿名类是在块中声明的,但它的上下文与创建它的上下文完全分离。必须防止对匿名类进行任何修改,因为无法在封闭范围内反映这些更改。同样,在封闭作用域中,变量必须保持不变,因为一旦匿名类捕获了其值,封闭作用域中的任何更改都无法反映到匿名类中。

如果您想使用

ScheduledThreadPoolExecutor

启动计时器,那么您不能依赖动态定义的类并使用封闭范围的变量。您需要声明一个扩展

Runnable
的类。在以下示例中,可以通过传递秒数、对调度程序的引用和消息数组来实例化
Timer
类。
class Timer implements Runnable {
    private ScheduledExecutorService scheduler;
    private int numSecs;

    private String[] vetMessages;

    public Timer(ScheduledExecutorService scheduler, int numSecs, String[] vetMessages) {
        this.scheduler = scheduler;
        this.numSecs = numSecs;
        this.vetMessages = vetMessages;
    }

    @Override
    public void run() {
        numSecs--;
        if (numSecs < 4) {
            System.out.println(vetMessages[numSecs]);
            if (numSecs <= 0) {
                scheduler.shutdown();
            }
        }
    }
}

class MyProgram {

    public static void main(String[] args) {
        Scanner input1 = new Scanner(System.in);
        System.out.println("What is your name");
        String personsName = input1.next();
        System.out.println((personsName) + " Are you ready to impove yourself");
        String motiv = input1.next();

        String[] myArray = new String[4];
        myArray[0] = "Keep going";
        myArray[1] = "1 more rep";
        myArray[2] = "you have come so far don't stop now";
        myArray[3] = "Think of the progress you have made";

        if (motiv.equals("yes")) {
            System.out.println("Today is the day hard work begins");
        } else {
            System.out.println("type yes when you're ready to work");
        }

        Scanner input2 = new Scanner(System.in);
        System.out.println("You will recive quotes throughout your workout to remind you to keep working type ok if you accept");
        String confirm = input2.next();

        if (confirm.equals("ok")) {
            final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
            Timer t = new Timer(scheduler, 10, myArray);

            //Added an initial delay of 1 second to not start the Timer immediately and decrement the number of seconds right away
            scheduler.scheduleAtFixedRate(t, 1, 1, TimeUnit.SECONDS);
        }
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.