线程;创建一个独立的线程定期执行某些操作

6
作为我当前应用程序的补充,我需要创建一个单独的线程,定期进行一些处理。
我已经创建了一个新类来完成所有这些工作,并且这个类将在我的应用程序启动时加载。
目前为止,这就是我所拥有的。
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
    }

}

我希望将构造函数私有化,以防止其他人意外实例化该类。我应该如何实现这一点?
另外,我的实现是否存在任何问题?我只创建了一个线程,它会运行然后休眠,我是否遗漏了什么明显的问题?我之前没有使用过线程。

1
在静态块中启动线程吗? :) - willcodejavaforfood
5个回答

14

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


10
您的代码存在一些概念性错误...例如:
  • 您应该调用start()而不是run(),因为您正在顺序运行该方法而不是同时运行。
  • 您只能调用一次start(),而不是在每个循环迭代中都调用。之后,线程处于TERMINATED状态,您应该创建一个新线程来再次运行它。
  • 您不应该在静态块中创建线程,这是一个不好的实践,可能会导致Thread在您想要运行之前就已经运行了。

您应该阅读一些关于线程的示例,这在开始时有点困难,您很容易产生不希望出现的影响。

这里有一个小例子,可能与您想要的类似:

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

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

while 循环后面少写了一个“}”哦 :) - Keshav

4

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

}

3

扩展Thread几乎从来都不是正确的做法。如果你发现自己在这样做,请退后一步,看看并问自己是否真的需要改变Thread类的工作方式。

我几乎每次看到extends Thread的情况下,最好的做法是实现Runnable接口或使用某种形式的Timer


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接