Java创建定期执行某些操作的后台线程
有没有可能创建一个单独的背景线程,分别做一些事情? 我试过下面的程序,但没有达到我的预期效果Java创建定期执行某些操作的后台线程,java,multithreading,Java,Multithreading,有没有可能创建一个单独的背景线程,分别做一些事情? 我试过下面的程序,但没有达到我的预期效果 public class Test { private static class UpdaterThread extends Thread { private final int TIMEOUT = 3000; public void run() { while (true) { try {
public class Test {
private static class UpdaterThread extends Thread {
private final int TIMEOUT = 3000;
public void run() {
while (true) {
try {
Thread.sleep(TIMEOUT);
System.out.println("3 seconds passed");
} catch (InterruptedException ex) {
}
}
}
}
/**
* @param args
* the command line arguments
*/
public static void main(String[] args) {
try {
Thread u = new UpdaterThread();
u.start();
while (true) {
System.out.println("--");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
我期望每3秒“3秒已过”将以多个“-”字符串的流打印。
事实上,“3秒过去”从未打印过。为什么?如何创建一个独立于主线程的后台线程?您可以使用上述方法定期运行任务,尽管
TimerTask
可能更简单
关于输出,我怀疑主线程不允许运行UpdaterThread
,因为它处于一个非常紧密的循环中。请注意,这将取决于可用的CPU/内核等
您是否考虑过在主线程中睡觉,或使用?请注意链接页面中的但书:
何时使用yield()
我想说,几乎从来没有。它的行为没有标准的定义
而且通常有更好的方法来完成您需要的任务
可能希望使用yield()执行:如果您仅尝试使用
在CPU部分,您可以通过以下方式以更可控的方式执行此操作:
估计线程在其最后一块内存中使用了多少CPU
处理,然后睡眠一段时间来补偿:参见
sleep()方法
还要注意处理线程中断。使用
java.util.TimerTask
和java.util.Timer
:
Timer t = new Timer();
t.scheduleAtFixedRate(
new TimerTask()
{
public void run()
{
System.out.println("3 seconds passed");
}
},
0, // run first occurrence immediately
3000); // run every three seconds
它会打印“3秒过去”。删除System.out.println(“-”
,您将更容易看到它们;-)
现在您还可以使用ScheduledExecutorService
,并使用Runnable
而不是线程
:
public class Test {
private static class Updater implements Runnable {
@Override
public void run() {
System.out.println("3 seconds passed");
}
}
public static void main(String[] args) throws InterruptedException {
Runnable r = new Updater();
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(r, 0, 3, TimeUnit.SECONDS);
Thread.sleep(10000);
service.shutdown();
}
}
我建议你使用一种新的方法。要每3秒钟运行一次UpdaterThread()
,可以执行以下操作:
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new UpdaterThread(), 0, 3000, TimeUnit.MILLISECONDS);
你可以在这里读到更多:。有很多答案,但是没有人说为什么他的例子不起作用
System.out
是输出流,所以在您开始写入此流之后,JAVA会锁定它,而所有其他线程都会在向流应用锁时等待。在流解锁后,另一个线程将能够使用此流
为了使您的示例有效,您应该在主线程中循环时将
线程添加到中。睡眠。不要扩展线程(很少有必要),而是实现可运行的,请看,当您捕获异常时,不对此执行任何操作很少是件好事。至少,您需要打印出异常是什么。否则,您甚至不知道是否捕获到异常。同意Arnab Datta,而是使用ex.printStackTrace()代码>永远不要让catch块为空,这比你有多少cpu内核没有意义吗?实际上catch(InterruptedException e)
处理程序显然应该包含一个中断
--或者在try块中插入。+1,对于OP some code@Sergey,是的。每个Timer
对象都有一个后台线程。有关详细信息,请参阅javadoc。@Sergey是的,TimerTask的优点是它能更好地表达您的意图(即代码可读性),并且它已经实现了cancel()功能…并在计时器调用期间绑定线程池线程-如果计时器回调本身进行阻塞调用。。。只是说-计时器任务并不总是最好的解决方案。@hmjd和其他人:对于我们不知道计时器任务将花费多少时间的场景,我想按精确的持续时间延迟执行,我们如何才能做到这一点?例如:计时器的第一次执行需要5秒,第二次需要3秒,第三次需要8秒等等,但我希望每次执行前都有准确的“睡眠”时间。因此,无论执行时间如何,我的延迟应该是相同的。我如何才能做到这一点?这似乎是最好的答案-I/O流被来自主线程的所有println()阻塞。使用计时器或ScheduledExecutorService是可以的,但实际上需要运行额外的线程,而且在一个具有许多函数调用的复杂线程中,当堆栈中的几层出现时,实现起来很困难/笨拙-它会迫使您进入一个您可能不想要/不需要的状态机。计时器等并不总是最好的答案@MartinJames它只需要运行一个额外的线程,而这正是OP所要求的。当你说“它强迫你进入一个你可能不想要/不需要的状态机”时,我不确定我是否理解。好的,例如:你的线程调用函数a,它调用函数B,它调用函数C,其中代码/数据指示需要等待2秒才能继续其操作并返回。对于操作代码,计时器/执行器是可以的——我只想说,计时器/执行器并不适用于所有需要等待的情况。不是我,但我怀疑下行投票者认为将这样的任务排队到线程池(或者使用计时器)可能会造成过度的、可避免的上下文更改?@MartinJames:可能是这样。他/她显然反对在这里使用ScheduledExecutorService,因为@assylias的答案也被否决了。那么,否决了吗?如果答案是完全错误的,我只会投反对票。如果我认为有更好的解决方案或更好的解释,我会添加一条评论。