主题;创建一个单独的线程来定期执行某些操作

时间:2010-11-03 11:02:42

标签: java multithreading thread-safety

作为我当前应用程序的补充,我需要创建一个单独的线程,它会定期进行一些处理

我已经创建了一个新类来完成所有这些操作,这个类将在我的应用程序启动时加载。

这是我到目前为止所做的:

public class PeriodicChecker extends Thread
{
    static
    {
        Thread t = new Thread(new PeriodicChecker());
        while(true)
        {
            t.run();
            try
            {
                Thread.sleep(5000l);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }

    /**
     * Private constructor to prevent instantiation
     */
    private PeriodicChecker()
    {

    }

    @Override
    public void run()
    {
        System.out.println("Thread is doing something");
        // Actual business logic here, that is repeated
    }

}

我想将构造函数设为私有,以防止其他人意外地尝试实例化此类。我怎样才能做到这一点?

另外,我对这些要求的实施有什么不好吗?我只创建一个会运行然后睡觉的线程,我是否错过了任何明显的错误?

之前我没有使用过线程

5 个答案:

答案 0 :(得分:12)

Java提供ScheduledExecutorService来安排和运行具有延迟的周期性任务或任务。它应该提供您需要的所有功能。 Timer是另一个提供类似功能的类,但我建议使用ScheduledExecutorService over Timer,因为它具有灵活的配置和更好的错误管理。

答案 1 :(得分:10)

您的代码中有一些概念错误...例如:

  • 你应该调用start()而不是run(),因为你是按顺序而不是同时运行方法。
  • 您只能在每次循环迭代中调用start()一次,而不是一次。之后,线程处于TERMINATED状态,您应该创建一个新线程再次运行它
  • 你不应该在静态块中创建线程,这是一个不好的做法,也许线程在你希望它运行之前就已经运行了。

你应该阅读一些关于线程的例子,一开始就有点难以理解,你很容易产生不良影响。

这是一个小例子,可以做一些你想要的事情:

public class PeriodicChecker extends Thread
{
    @Override
    public void run()
    {
        while(true) {
           System.out.println("Thread is doing something");
           Thread.sleep(5000);
        }
    }

}

public OtherClass {
   public static void main(String args[]) {
      Thread t = new PeriodicChecker();
      t.start();
   }
}

如果你想要没有人可以创建一个新的线程,你可以创建一个单例,这样你就可以确保没有人创建更多的线程。

答案 2 :(得分:4)

我建议您考虑Timer class - 它提供定期任务执行的功能。 您也可以查看"Timer & TimerTask versus Thread + sleep in Java"问题讨论 - 在那里您可以找到一些参数和示例。

答案 3 :(得分:3)

首先要回答您的具体问题,您已经实现了目标。您已将您的构造函数声明为私有,这意味着没有外部类可以像new PeriodicChecker()一样调用它。

然而,查看您的代码还有许多其他问题:

首先,您要在自己的静态构造函数中创建类的实例。静态构造函数的目的是初始化您的类可能具有的任何静态状态,然后您的类的哪些实例可能依赖于该状态。通过在静态构造函数中创建类的实例,所有这些保证就会消失。

其次,我不认为你的线程会以你期望它的行为方式运行,主要是因为你实际上没有启动另一个线程:)。如果您打算启动一个新线程,则需要在该线程对象上调用start()方法。像你一样调用run()实际上并不创建新线程,而只是在当前线程中运行run()方法。

现在,当你想创建一个新的线程来做某事时,实现这一点的推荐方法是不扩展Thread,而是实现Runnable接口。这允许您将线程的机制与您打算运行的行为分离。

根据您的要求,我建议不要使用像这样的顶级类,而是在应用程序启动代码中创建一个私有内部类,或者甚至去一个匿名内部类:

public class Main {

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true) {
                    System.out.println("Thread is doing something");
                    Thread.sleep(5000);
                }
            }
        }).start();
    }

}

答案 4 :(得分:2)

几乎从不Thread进行扩展。如果你发现自己这样做了,请退一步看看自己是否真的需要改变Thread类的工作方式。

几乎所有出现,我看到extends Thread这项工作最好在实施Runnable界面或使用某种形式的Timer时完成。