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的答案也被否决了。那么,否决了吗?如果答案是完全错误的,我只会投反对票。如果我认为有更好的解决方案或更好的解释,我会添加一条评论。