【问题标题】:What is the equivalent of javascript setTimeout in Java?Java 中的 javascript setTimeout 等价物是什么?
【发布时间】:2014-12-06 08:01:45
【问题描述】:

我需要实现一个在单击按钮 60 秒后运行的函数。请帮忙,我使用了 Timer 类,但我认为这不是最好的方法。

【问题讨论】:

标签: java javascript timer settimeout setinterval


【解决方案1】:

underscore-java 库中有setTimeout() 方法。

代码示例:

import com.github.underscore.Underscore;
import java.util.function.Supplier;

public class Main {

    public static void main(String[] args) {
        final Integer[] counter = new Integer[] {0};
        Supplier<Void> incr =
            () -> {
                counter[0]++;
                return null;
            };
        Underscore.setTimeout(incr, 0);
    }
}

该函数将在 100 毫秒内启动一个新线程。

【讨论】:

  • 绝对不适合使用任何类型的“睡眠”(在主线程或活动线程上)来执行此类操作。 (也不需要使用线程。)正如这里所建议的,某种超时绝对是需要的。另外:在超时处理程序中,请确保您验证感兴趣的条件仍然存在! (即使您在条件不再存在时“删除超时”,仍然存在一个您无法完全消除的微小计时孔。)
【解决方案2】:

使用java.util.Timer

new Timer().schedule(new TimerTask() {
    @Override
    public void run() {
        // here goes your code to delay
    }
}, 300L); // 300 is the delay in millis

Here你可以找到一些信息和例子。

【讨论】:

  • 谢谢,我还需要 clearTimeout() 替代方法,所以用法是... Timer timer = new Timer(); timer.schedule(...); timer.cancel();
【解决方案3】:

使用 Java 9 CompletableFuture,一切都很简单:

CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS).execute(() -> {
  // Your code here executes after 5 seconds!
});

【讨论】:

  • Snippet not working 它显示错误:The method delayedExecutor(int, TimeUnit) is undefined for the type CompletableFuture
  • 我想我弄错了,它是针对 Java 9,而不是 Java 8。使用 Java 9,一切都很好。
  • 对于任何使用 java 9 及更高版本的人来说,这应该是公认的答案
【解决方案4】:

“我使用了 Timer 类,但我认为这不是最好的方法。”

其他答案假设您没有使用 Swing 作为您的用户界面(按钮)。

如果您使用的是 Swing,请不要使用Thread.sleep(),因为它会冻结您的 Swing 应用程序。

您应该使用javax.swing.Timer

有关更多信息和示例,请参阅 Java 教程 How to Use Swing TimersLesson: Concurrency in Swing

【讨论】:

  • 尽管这是公认的答案,但它已经过时了,尤其是自 java 9 出现以来。请参阅下面关于delayedExecutor的答案
【解决方案5】:
public ScheduledExecutorService = ses;
ses.scheduleAtFixedRate(new Runnable(){
    run(){
            //running after specified time
}
}, 60, TimeUnit.SECONDS);

它在 scheduleAtFixedRate 60 秒后运行 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html

【讨论】:

  • 您能分享一下您的解决方案比其他解决方案更好的地方吗?并且请解释您的解决方案在做什么,而不是仅仅粘贴一段代码。
  • 代码创建者不是我。它的神谕。比我好,他们必须解释。请参考此链接并阅读文档。docs.oracle.com/javase/7/docs/api/java/util/concurrent/…
【解决方案6】:

不要使用Thread.sleep,否则它会冻结你的主线程并且不会从 JS 模拟 setTimeout。您需要创建并启动一个新的后台线程来运行您的代码,而无需停止主线程的执行。像这样:

new Thread() {
    @Override
    public void run() {
        try {
            this.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        // your code here

    }
}.start();

【讨论】:

    【解决方案7】:

    使用JDK 1.8的异步实现:

    public static void setTimeout(Runnable runnable, int delay){
        new Thread(() -> {
            try {
                Thread.sleep(delay);
                runnable.run();
            }
            catch (Exception e){
                System.err.println(e);
            }
        }).start();
    }
    

    使用 lambda 表达式调用:

    setTimeout(() -> System.out.println("test"), 1000);
    

    或者有方法参考:

    setTimeout(anInstance::aMethod, 1000);
    

    处理当前运行的线程只使用同步版本:

    public static void setTimeoutSync(Runnable runnable, int delay) {
        try {
            Thread.sleep(delay);
            runnable.run();
        }
        catch (Exception e){
            System.err.println(e);
        }
    }
    

    在主线程中谨慎使用它——它会在调用之后暂停所有内容,直到 timeout 到期并且 runnable 执行。

    【讨论】:

    • 是的,不要这样做 - 它会启动太多线程,我认为 CompletableFuture 技术更好
    • CompletableFuture 仍然会创建一个新线程。见CompletableFuture.java#2745
    • 呵呵,有没有办法告诉 CompletableFuture 使用线程池而不是每次都创建一个新线程?还是已经这样做了?
    • 即使是 Java 的内置 Timer class 也启动了“线程过多”:“一种线程安排任务以供将来在后台线程中执行的工具。”我认为这种方式实际上很干净。它不处理重复执行的情况,但你总是可以让你的任务在最后再次调用 settimeout。
    【解决方案8】:

    您可以简单地使用Thread.sleep() 来实现此目的。但是,如果您在具有用户界面的多线程环境中工作,您可能希望在单独的线程中执行此操作,以避免睡眠阻塞用户界面。

    try{
        Thread.sleep(60000);
        // Then do something meaningful...
    }catch(InterruptedException e){
        e.printStackTrace();
    }
    

    【讨论】:

      【解决方案9】:

      您应该使用Thread.sleep() 方法。

      try {
      
          Thread.sleep(60000);
          callTheFunctionYouWantTo();
      } catch(InterruptedException ex) {
      
      }
      

      这将等待 60,000 毫秒(60 秒),然后执行代码中的下一条语句。

      【讨论】:

        猜你喜欢
        • 2012-02-05
        • 1970-01-01
        • 2014-07-27
        • 2012-02-02
        • 2021-09-21
        • 2010-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多