我有一个特定的函数,希望在5秒后执行。如何在Java中实现这个功能?
我找到了javax.swing.timer,但是我无法理解如何使用它。看起来我正在寻找比这个类提供的更简单的东西。
请添加一个简单的使用示例。
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
public void run() {
// your code here
}
},
5000
);
编辑:
javadoc指出:
在最后一个对 Timer 对象的活动引用消失并且所有未完成的任务都已执行完成之后,计时器的任务执行线程会优雅地终止(并成为垃圾回收的对象)。但是,这可能需要任意长的时间才能发生。
import java.util.Timer; import java.util.TimerTask;
可能会更明显地表明这不是 javax.swing.Timer
。需要注意的是,如果你正在使用 Swing(实际上也包括 AWT),你不应该在非事件分派线程(EDT)上改变组件(java.util.Timer
的任务不好;javax.swing.Timer
的操作则可行)。 - Tom Hawtin - tacklinecancel
方法会在运行方法结束时清除TimerTasks的执行线程。 - Dandalf类似这样:
// 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();
如果您需要更多线程池中的线程,可以使用Executor
上的其他各种工厂方法。
请记住,在完成后关闭执行器非常重要。 shutdown()
方法将在最后一个任务完成时清除关闭线程池,并阻塞直到完成此操作。 shutdownNow()
将立即终止线程池。
shutdown()
不会阻塞。而 awaitTermination()
会。 - Yonasshutdown()
只是不允许提交新任务。 shutdownNow()
还会中断任务(不一定立即终止)。 - dan1st使用 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!
这段代码只会执行一次,在3秒(3000毫秒)后执行。
正如camickr所提到的,您应该查阅 "如何使用Swing Timer" 来进行简短的介绍。
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
);
Timer t
应该声明为 final
吗?因为它被内部类访问了。 - Joshua Pinter我的代码如下:
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
);
您原始的问题提到了“Swing Timer”。如果您的问题确实与Swing有关,则应使用Swing Timer而不是util.Timer。
请阅读Swing教程中关于“如何使用计时器”的部分以获取更多信息。
Thread.sleep(4000);
myfunction();
您的函数将在4秒后执行。然而,这可能会暂停整个程序...
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();
}
}
测试:
@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());
}
while
只是为了忽略中断。 - AlikElzin-kilaka所有其他答案都需要在新线程中运行您的代码。在某些简单的用例中,您可能只想等一会儿,然后在同一个线程/流中继续执行。
下面的代码演示了这种技术。请记住,这类似于java.util.Timer在内部执行的操作,但更加轻量级。
import java.util.concurrent.TimeUnit;
public class DelaySample {
public static void main(String[] args) {
DelayUtil d = new DelayUtil();
System.out.println("started:"+ new Date());
d.delay(500);
System.out.println("half second after:"+ new Date());
d.delay(1, TimeUnit.MINUTES);
System.out.println("1 minute after:"+ new Date());
}
}
DelayUtil实现
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class DelayUtil {
/**
* Delays the current thread execution.
* The thread loses ownership of any monitors.
* Quits immediately if the thread is interrupted
*
* @param duration the time duration in milliseconds
*/
public void delay(final long durationInMillis) {
delay(durationInMillis, TimeUnit.MILLISECONDS);
}
/**
* @param duration the time duration in the given {@code sourceUnit}
* @param unit
*/
public void delay(final long duration, final TimeUnit unit) {
long currentTime = System.currentTimeMillis();
long deadline = currentTime+unit.toMillis(duration);
ReentrantLock lock = new ReentrantLock();
Condition waitCondition = lock.newCondition();
while ((deadline-currentTime)>0) {
try {
lock.lockInterruptibly();
waitCondition.await(deadline-currentTime, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
} finally {
lock.unlock();
}
currentTime = System.currentTimeMillis();
}
}
}
public static Timer t;
public synchronized void startPollingTimer() {
if (t == null) {
TimerTask task = new TimerTask() {
@Override
public void run() {
//Do your work
}
};
t = new Timer();
t.scheduleAtFixedRate(task, 0, 1000);
}
}