Java 我怎样才能使一个线程睡眠一段时间,然后再开始工作?

Java 我怎样才能使一个线程睡眠一段时间,然后再开始工作?,java,multithreading,thread-sleep,Java,Multithreading,Thread Sleep,我有以下代码: public void run() { try { logger.info("Looking for new tasks to fetch... "); // definitions .. for(Task t: tasks) { logger.info(" Task " + t.getId() + " is being fetched ");

我有以下代码:

public void run() 
{
     try 
     {
         logger.info("Looking for new tasks to fetch...  ");
         // definitions ..

         for(Task t: tasks)
         {
             logger.info(" Task " + t.getId() + " is being fetched ");
            // processing ... fetching task info from db using some methods
         }
         Thread.sleep(FREQUENCY);
         //t.start();
     } catch (Exception e) 
     {
         logger.info("FetcherThread interrupted: "+e.getMessage());
     }
}
我试图让线程在特定的时间“频率”内休眠,然后再次工作。当我在eclipse中执行这段代码时,线程只工作一次,然后什么也不发生,进程终止。如果我从语句中删除注释:
t.start()
,我会得到“FetcherThreadInterrupted:null”。 谁能告诉我哪里出了问题


注意:我希望线程一直工作,但在周期(比如每5分钟)上取数。

尝试在不同的线程上执行任务。

您需要将睡眠置于无限循环中(或者在需要睡眠时指定正常运行时间的条件下)。到目前为止,sleep方法是在run方法的末尾调用的,您观察到的行为是正确的。 下面的演示代码将在睡眠一秒钟后在控制台上打印“睡眠”。希望能有帮助

import java.util.concurrent.TimeUnit;

public class Test implements Runnable {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Test t = new Test();
        Thread thread = new Thread(t);
        thread.start();
    }

    public void run() {
        try {
            // logger.info("Looking for new tasks to fetch...  ");
            // definitions ..

            // for(Task t: tasks)
            // {
            // logger.info(" Task " + t.getId() + " is being fetched ");
            // // processing ... fetching task info from db using some methods
            // }
            while (true) { // your condition here
                TimeUnit.SECONDS.sleep(1);
                System.out.println("Sleep");
            }

            // t.start();
        } catch (Exception e) {
            // logger.info("FetcherThread interrupted: "+e.getMessage());
        }
    }
}

代码中缺少任何类型的循环

看起来这个线程实际上在做你让它做的事情:它运行所有的任务,然后休眠一段时间——然后它没有更多的工作要做,所以退出。有几种方法可以解决这个问题,按复杂性和正确性的升序排列:

  • 解决这一问题的简单(且简单)方法是将try-catch块包装在无限循环中(
    while(true){…}
    )。这样,在线程完成睡眠后,它将循环回到顶部,并再次处理所有任务

  • 但是这并不理想,因为基本上不可能停止线程。更好的方法是声明一个布尔字段(例如,
    boolean running=true;
    ),并在(运行)时将循环更改为
    。这样,您就有了一种使线程终止的方法(例如,公开一个将
    running
    设置为
    false
    的方法)。有关这一点的详细解释,请参阅Sun的文章

  • 再往后退一步,你可能试图在一个太低的水平上做到这一点。睡眠和日程安排并不是真正的
    可运行的
    工作的一部分。我将采用的实际解决方案是去掉休眠,这样您就有了一个可运行的实现,它处理所有任务,然后终止。然后我将创建一个,并将“普通”可运行的提交给执行者——这样,执行者的工作就是定期运行任务


  • 从工程角度来看,最后一个解决方案是理想的。您有一个只运行一次作业并退出的类—只要您想运行作业,就可以在其他上下文中使用它,并且组合得非常好。您有一个executor服务,其任务是调度任意任务-同样,您可以在将来将不同类型的
    Runnable
    Callable
    传递给该服务,它也将执行调度位。可能最棒的是,您不必自己编写任何调度内容,但可以使用标准库中的一个类专门为您完成这一切(因此可能已经解决了大多数bug,而不是自行生成的并发代码).

    您需要某种循环来重复您的工作流程。控制流应如何返回到提取部件

    您可以将代码放入一个循环中。(可能是while)


    您的案例中发生了什么?它运行任务循环,然后休眠一段时间并退出线程。

    将线程放入循环中,正如其他人在这里提到的那样

    我想补充一点,多次调用Thread.start是非法的,这就是为什么会出现异常

    如果要生成多个线程,请为要启动的每个线程创建一个线程对象

    见()


    将成员调用keepRunning添加到主线程中,并实现一个访问器方法,将其设置为false(从需要阻止线程执行任务的任何位置开始)

    任务调度在Java中具有一流的支持,不要重新发明它。实际上,有两种
    实现:
    Timer
    (老式)和
    ScheduledExecutorService
    (新)。阅读它们并围绕它们设计应用程序。

    您可以尝试
    ScheduledExecutorService
    ()。 而美国则是
    scheduleAtFixedRate
    ,它:

    创建并执行一个周期性动作,该动作在给定的初始延迟后首先启用,然后在给定的时间段内启用;也就是说,执行将在initialDelay之后开始,然后是initialDelay+period,然后是initialDelay+2*period,依此类推


    如果取消注释
    t.start()
    ,则会出现编译器错误,无法运行它。谢谢@Andrzej。。我找到了ScheduledExtructorService()的代码示例,它展示了如何使用它而不是无限循环
    while(condition) // you can make it while(true) if you want it to run infinitely.
    {
          for(Task t: tasks)
         {
             logger.info(" Task " + t.getId() + " is being fetched ");
            // processing ... fetching task info from db using some methods
         }
         Thread.sleep(FREQUENCY);
    }
    
    public void run() 
    {
        while (keepRunning) {
            try 
            {
                logger.info("Looking for new tasks to fetch...  ");
                // definitions ..
    
                for(Task t: tasks)
                {
                    logger.info(" Task " + t.getId() + " is being fetched ");
                    // processing ... fetching task info from db using some methods
                    t.start();
                }
                Thread.sleep(FREQUENCY);
    
            } catch (Exception e) {
                keepRunning = false;
                logger.info("FetcherThread interrupted: "+e.getMessage());
            }  
        }
    }