10

是否可以创建一个单独的后台线程来单独做一些事情?我已经尝试了以下程序,但它没有按我的预期工作。

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 秒过去”从未被打印出来。为什么?以及如何创建一个独立于主线程做某事的后台线程?

4

5 回答 5

19

使用java.util.TimerTaskjava.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
于 2012-07-17T10:44:18.197 回答
7

它确实打印“经过 3 秒”。删除System.out.println("--"),你会更容易看到它们;-)

现在您也可以使用 a ScheduledExecutorService,并使用 aRunnable而不是 a Thread

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();

    }
}
于 2012-07-17T10:47:44.363 回答
3

您可以使用上述方法定期运行内容,尽管 aTimerTask可能更简单。

关于您的输出,我怀疑您的主线程不允许您UpdaterThread运行,因为它处于非常紧密的循环中。请注意,这将取决于可用的 CPU/内核等。

您是否考虑过在线程中休眠或使用Thread.yield()?请注意该链接页面中的附带条件:

何时使用 yield()?

我会说几乎从不。它的行为没有标准定义,通常有更好的方法来执行您可能希望使用 yield() 执行的任务:如果您尝试仅使用一部分 CPU,您可以以更可控的方式执行此操作通过估计线程在其最后一个处理块中使用了多少 CPU,然后休眠一段时间来补偿:参见 sleep() 方法;

还要注意这篇关于处理线程中断的有趣文章。

于 2012-07-17T10:43:56.597 回答
2

有很多答案,但没有人说为什么他的例子不起作用。System.out是输出流,因此在您开始写入此流之后,JAVA 会锁定它,并且所有其他线程将等待锁定应用于流。流解锁后,另一个线程将能够使用此流。

为了使您的示例正常工作,您应该在主线程中添加Thread.sleep循环while

于 2012-07-17T18:53:11.510 回答
1

我建议使用ScheduledExecutorService. 要UpdaterThread()每 3 秒运行一次,您可以这样做:

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new UpdaterThread(), 0, 3000, TimeUnit.MILLISECONDS);

您可以在此处阅读更多内容:Java 教程 - 执行器接口

于 2012-07-17T10:47:57.093 回答