java:在特定秒数后运行一个函数

ufk*_*ufk 134 java timer

我有一个特定的功能,我希望在5秒后执行.我怎么能用Java做到这一点?

我找到了javax.swing.timer,但我真的不明白如何使用它.看起来我正在寻找比这个类提供的更简单的东西.

请添加一个简单的用法示例.

tan*_*ens 207

new java.util.Timer().schedule( 
        new java.util.TimerTask() {
            @Override
            public void run() {
                // your code here
            }
        }, 
        5000 
);
Run Code Online (Sandbox Code Playgroud)

编辑:

javadoc说:

在对Timer对象的最后一次实时引用消失并且所有未完成的任务都已完成执行之后,计时器的任务执行线程正常终止(并且变为垃圾回收).但是,这可能会发生任意长的时间.

  • 那你怎么去清理松散的线呢? (17认同)
  • `import java.util.Timer; import java.util.TimerTask;`可能会更明显这不是`javax.swing.Timer`./注意,如果你使用Swing(实际上是AWT)你不应该做任何事情来改变非事件调度线程(EDT)线程上的组​​件(`java.util.Timer` tasks bad;`javax.swing.Timer "行动好". (5认同)
  • 如果运行该代码,就会泄漏线程。完成后请务必清理计时器。 (3认同)
  • @PaulAlexander根据文档 - 在run方法结束时调用timer的`cancel`方法将清除TimerTasks的执行线程. (2认同)
  • 2021这里问一下,还需要手动清线程吗? (2认同)

ska*_*man 52

像这样的东西:

// When your program starts up
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

// then, when you want to schedule a task
Runnable task = ....    
executor.schedule(task, 5, TimeUnit.SECONDS);

// and finally, when your program wants to exit
executor.shutdown();
Run Code Online (Sandbox Code Playgroud)

Executor如果您想在池中添加更多线程,则可以使用其他各种工厂方法.

请记住,完成后关闭执行程序非常重要.该shutdown()方法将在最后一个任务完成时干净地关闭线程池,并将阻塞直到发生这种情况.shutdownNow()将立即终止线程池.


zpo*_*pon 23

使用示例 javax.swing.Timer

Timer timer = new Timer(3000, new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent arg0) {
    // Code to be executed
  }
});
timer.setRepeats(false); // Only execute once
timer.start(); // Go go go!
Run Code Online (Sandbox Code Playgroud)

此代码仅执行一次,执行时间为3000毫秒(3秒).

正如camickr所提到的,您应该查找" 如何使用摆动计时器 "进行简短介绍.


cam*_*ckr 7

您原来的问题提到了“Swing Timer”。如果实际上您的问题与 SWing 有关,那么您应该使用 Swing Timer 而不是 util.Timer。

请阅读 Swing 教程中有关“如何使用计时器”的部分以获取更多信息。


小智 6

我的代码如下:

new java.util.Timer().schedule(

    new java.util.TimerTask() {
        @Override
        public void run() {
            // your code here, and if you have to refresh UI put this code: 
           runOnUiThread(new   Runnable() {
                  public void run() {
                            //your code

                        }
                   });
        }
    }, 
    5000 
);
Run Code Online (Sandbox Code Playgroud)


dal*_*ale 5

您可以使用 Thread.Sleep() 函数

Thread.sleep(4000);
myfunction();
Run Code Online (Sandbox Code Playgroud)

您的函数将在 4 秒后执行。然而,这可能会暂停整个程序......

  • questzen,您会发现这里*所有*方法都可以做到这一点。事实上,即使您在操作系统级别安排某些事情,通常也只能保证事件发生之前的最短运行时间。 (2认同)

Ali*_*aka 5

ScheduledThreadPoolExecutor有这个能力,可是相当重量级的。

Timer也有这种能力,但即使只使用一次也会打开多个线程。

这是一个带有测试的简单实现(签名接近 Android 的Handler.postDelayed()):

public class JavaUtil {
    public static void postDelayed(final Runnable runnable, final long delayMillis) {
        final long requested = System.currentTimeMillis();
        new Thread(new Runnable() {
            @Override
            public void run() {
                // The while is just to ignore interruption.
                while (true) {
                    try {
                        long leftToSleep = requested + delayMillis - System.currentTimeMillis();
                        if (leftToSleep > 0) {
                            Thread.sleep(leftToSleep);
                        }
                        break;
                    } catch (InterruptedException ignored) {
                    }
                }
                runnable.run();
            }
        }).start();
    }
}
Run Code Online (Sandbox Code Playgroud)

测试:

@Test
public void testRunsOnlyOnce() throws InterruptedException {
    long delay = 100;
    int num = 0;
    final AtomicInteger numAtomic = new AtomicInteger(num);
    JavaUtil.postDelayed(new Runnable() {
        @Override
        public void run() {
            numAtomic.incrementAndGet();
        }
    }, delay);
    Assert.assertEquals(num, numAtomic.get());
    Thread.sleep(delay + 10);
    Assert.assertEquals(num + 1, numAtomic.get());
    Thread.sleep(delay * 2);
    Assert.assertEquals(num + 1, numAtomic.get());
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*alf 5

作为@tangens的一个变体:如果您迫不及待想要垃圾回收器清理线程,请在run方法结束时取消计时器。

Timer t = new java.util.Timer();
t.schedule( 
        new java.util.TimerTask() {
            @Override
            public void run() {
                // your code here
                // close the thread
                t.cancel();
            }
        }, 
        5000 
);
Run Code Online (Sandbox Code Playgroud)