Java 如何将 TimerTask 与 lambdas 一起使用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22378422/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:23:46  来源:igfitidea点击:

How to use TimerTask with lambdas?

javalambdaabstract-classtimertaskjava-8

提问by skiwi

As you hopefully know you can use lambdas in Java 8, for example to replace anonymous methods.

正如您希望知道的那样,您可以在 Java 8 中使用 lambda,例如替换匿名方法。

An example can be seen here of Java 7 vs Java 8:

可以在此处看到 Java 7 与 Java 8 的示例:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        checkDirectory();
    }
};

Can be expressed as both the following ways in Java 8:

在 Java 8 中可以表示为以下两种方式:

Runnable runnable = () -> checkDirectory();

or

或者

Runnable runnable = this::checkDirectory;

This is because Runnableis a functional interface, having only one (abstract) public non-default method.

这是因为Runnable是一个函数式接口,只有一个(抽象的)公共非默认方法。

However... For TimerTaskwe have the following:

但是......因为TimerTask我们有以下内容:

TimerTask timerTask = new TimerTask() {
    @Override
    public void run() {
        checkDirectory();
    }
};

Looks familiar, right?
Using a lambda expression does not work though, because TimerTaskis an abstract class, even though it has only one abstract public non-default method, it is not an interface and hence no functional interface either.
It is also not refactored into an interface with default implementations, because it carries state, so that cannot be done then.

看起来很熟悉对不对?
但是使用 lambda 表达式不起作用,因为它TimerTask是一个抽象类,即使它只有一个抽象的公共非默认方法,它也不是一个接口,因此也没有功能接口。
它也没有被重构为具有默认实现的接口,因为它携带状态,因此无法完成。

So my question: Is there any way to use lambdas when constructing the TimerTask?

所以我的问题是:在构造TimerTask.

What I wanted is the following:

我想要的是以下内容:

Timer timer = new Timer();
timer.schedule(this::checkDirectory, 0, 1 * 1000);

Instead of some ugly anonymous inner class, is there any way to make it nicer?

除了一些丑陋的匿名内部类,有没有办法让它更好?

采纳答案by Marko Topolnik

Noting first that Timeris effectively an antiquated API, but entertaining your question nevertheless, you could write a small wrapper around it which would adapt the schedulemethod to accept a Runnable, and on the inside you'd turn that Runnableinto a TimerTask. Then you would have your schedulemethod which would accept a lambda.

首先请注意,这Timer实际上是一个过时的 API,但尽管如此,还是可以娱乐您的问题,您可以围绕它编写一个小包装器,使该schedule方法能够接受 a Runnable,并在内部将其Runnable转换为TimerTask. 然后,您将拥有schedule接受 lambda 的方法。

public class MyTimer {
  private final Timer t = new Timer();

  public TimerTask schedule(final Runnable r, long delay) {
     final TimerTask task = new TimerTask() { public void run() { r.run(); }};
     t.schedule(task, delay);
     return task;
  }
}

回答by Fran?ois SAMIN

To complete Marko Topolnik's answer about Timer, you just have to call schedulemethod with a lambda.

要完成 Marko Topolnik 关于 的回答Timer,您只需schedule使用 lambda调用方法。

schedule(() -> {
    System.out.println("Task #1 is running");
}, 500);

回答by lapsus63

You can also create a Timer easily with lambdas from the Swing API if you want (but not with TimerTask) :

如果需要,您还可以使用 Swing API 中的 lambdas 轻松创建计时器(但不能使用 TimerTask):

new javax.swing.Timer(1000, (ae) -> this::checkDirectory).start();

new javax.swing.Timer(1000, (ae) -> this::checkDirectory).start();

回答by Kalec

While Marko's answer is perfectly correct, I prefer my implementation:

虽然 Marko 的回答是完全正确的,但我更喜欢我的实现:

public class FunctionalTimerTask extends TimerTask {

    Runnable task;

    public FunctionalTimerTask(Runnable task) {
        this.task = task;
    }

    @Override
    public void run() {
        task.run();
    }
}

 public static class Task {
    public static TimerTask set(Runnable run) {
        return new FunctionalTimerTask(() -> System.err.println("task"));
    }
}

 Timer timer = new Timer(false);
 timer.schedule(Task.set(() -> doStuff()), TimeUnit.SECONDS.toMillis(1));

This gives you more control over the timer, and you have a static utility class. Idealy give it a name that won't conflict with other common thread class, so not Task, Job, Timer.

这使您可以更好地控制计时器,并且您有一个静态实用程序类。理想情况下,给它一个不会与其他公共线程类冲突的名称,所以不要给它 Task、Job、Timer。