创建一个永无止境的线程

时间:2014-07-23 06:54:13

标签: java multithreading

我想创建一个永不停止的线程。它每秒都会获得系统时间并在控制台上显示。这就是我到目前为止所做的:

public class Test implements Runnable {

    @Override
    public void run() {
        System.out.println(System.currentTimeMillis());
    }
}

我想避免使用循环。

1 个答案:

答案 0 :(得分:2)

使用while(true)TimeUnit.SECONDS.sleep是可能的,但这是不好的做法(正如你可以从这篇帖子中的大量下线看到的那样)。 This SO answer给出了原因:

  • 低级别,受到虚假的唤醒
  • 时钟漂移
  • 控制
  • 代码意图

还有其他人。

实现此目标的基本方法是使用java.util.Timer,不要与javax.swing.Timer混淆:

final Timer timer = new Timer("MyTimer");
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        System.out.println(System.currentTimeMillis());
    }
}, 0, TimeUnit.SECONDS.toMillis(1));

您需要调用timer.cancel()来停止计时器 - 因为计时器正在运行非守护程序线程,程序将不会退出,直到完成为止。

一种更高级的方法,允许将多个任务安排在ScheduledExecutorService的池上以不同的时间间隔运行。这允许你scheduleAtFixedRate每秒运行一个任务(无论运行多长时间,即 start 时间之间的差距始终相同)或scheduleWithFixedDelay以一秒的间隔运行任务(即一次运行结束与下一次运行结束之间的差距始终相同)。

例如:

final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
final ScheduledFuture<?> handle = executorService.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        System.out.println(System.currentTimeMillis());
    }
}, 0, 1, TimeUnit.SECONDS);

要取消您要拨打handle.cancel(false)的特定任务(由于中断无效)并停止executorService,您可以致电executorService.shutdown(),之后您可能需要添加executorService.awaitTermination(1, TimeUnit.DAYS) 1}}等待所有任务完成。

修改

评论这可以在java 8中使用lambda更简洁地完成吗? (不是lambdas的专家)

第一个例子,没有。 Timer需要TimerTask,这是abstract class而不是@FunctionalInterface所以lambda是不可能的。在第二种情况下,确定:

final ScheduledFuture<?> handle = executorService.
        scheduleAtFixedRate(() -> System.out.println(System.currentTimeMillis()), 0, 1, TimeUnit.SECONDS);