3

我正在尝试编写一个简单的 Java 程序,当分针为 20 时,它每小时运行一些代码。问题是我这样做的方式非常耗费 CPU。我熟悉石英,但我正在寻找一个更简单的解决方案,有什么想法吗?

    boolean run = true;
    while(run){
        Calendar calendar = new GregorianCalendar();
        int minute = calendar.get(Calendar.MINUTE);
        if(minute == 20){
            //Do some Stuff             
        }
    }
4

13 回答 13

5

一个简单的解决方案是使用 Executors 框架:

final ScheduledExecutorService s = Executors.newSingleThreadScheduledExecutor();
s.scheduleAtFixedRate(task, secondsToFirstOccurence, 60*60, TimeUnit.SECONDS);

并使用一些逻辑来找出答案secondsToFirstOccurence。这可能会涉及一个Calendar实例,但使用 JodaTime 会更方便。

于 2012-10-12T20:38:24.393 回答
2

请注意,如果您的应用程序在托管环境(Web 或 ejb 容器)中运行,则不允许您使用Thread.sleep()或任何其他与线程相关的操作,就此而言,请查看EJB 限制页面。我对此提出警告是因为问题已标记为java-ee,因此“简单应用程序”毕竟可能不是那么简单 - 如果它在 Java EE 容器中运行,则需要注意其他事项。

如果您正在构建企业级应用程序,请忘记Thread.sleep(). 选择一个成熟的作业调度器,使用Quartz,它是一个开源且非常成熟和可靠的产品。或者使用Obsidian Scheduler,这是一个功能丰富的商业调度程序,具有比 Quartz 更多的开箱即用功能。

一个完整的调度程序(但适合在容器内运行)的轻量级替代方案是使用Timer 服务

于 2012-10-12T20:31:21.513 回答
1

Thread.sleep()您可能在通话之间寻找

于 2012-10-12T20:28:59.083 回答
1

查看java.util.Timer方法 scheduleAtFixedRate()。

于 2012-10-12T20:34:24.403 回答
1

我建议您从 java 程序中删除调度逻辑。
通过这样做,您可以只专注于您希望程序执行的操作,并将调度部分留给操作系统。
另外,例如,假设您决定在某个时候编写一个 c++ 程序来执行您的 java 代码所知道的操作,您不必在新程序中实现 cron 逻辑

话虽这么说:

  • 对于 Linux,你有crontab
  • 对于 Windows,您有Windows 任务计划
  • 对于 Mac,我不确定,但考虑到它是基于 UNIX 的 cron 应该存在。
于 2012-10-17T10:57:03.347 回答
0

将您的代码无限期地使用并使用

Thread.sleep(3600000);

20点后开始执行

例子

while(1==1) {
    //Your code here
    try{
         Thread.sleep(3600000);
    }
    catch (Exception e) {}
}
于 2012-10-12T20:29:19.110 回答
0

为您想要每小时执行的方法安排一个 cron 作业,而不是阻塞sleep()调用,使用一些调度框架,如石英

于 2012-10-12T20:32:33.597 回答
0

1)在第一次进入计算下一个到期时间。

2) 使用java.util.Timer.schedule()

3) 重新安排每次运行。

代码

package tests;

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class App201210130040 {


private static Timer timer = new Timer(false);

public static void schedule() {
    Calendar due = Calendar.getInstance();
    due.set(Calendar.MINUTE, 20);
    if( due.before(Calendar.getInstance()) ) {
        due.add(Calendar.HOUR, 1);
    }

    System.out.println("Scheduled to " + due.getTime().toString());

    timer.schedule(new TimerTask() {

        @Override
        public void run() {

            System.out.println("due");

            schedule();
        }

    }, due.getTime());

}


public static void main(String[] args) {
    schedule();
}

}
于 2012-10-12T20:35:52.247 回答
0

你应该看看 ScheduledExecutorService

class BeeperControl {
private final ScheduledExecutorService scheduler = 
   Executors.newScheduledThreadPool(1);

public void beepForAnHour() {
    final Runnable beeper = new Runnable() {
            public void run() { System.out.println("beep"); }
        };
    final ScheduledFuture<?> beeperHandle = 
        scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
    scheduler.schedule(new Runnable() {
            public void run() { beeperHandle.cancel(true); }
        }, 60 * 60, SECONDS);
}
}
于 2012-10-12T20:36:39.467 回答
0

使用这样的东西

Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 20);
calendar.set(Calendar.MINUTE, 20);
calendar.set(Calendar.SECOND, 0);
Date time = calendar.getTime();
Timer timer = new Timer();
timer.schedule(new SomeTask(), time);

然后重新安排

于 2012-10-12T20:38:40.847 回答
0

因此,正如许多其他答案所述, ScheduledExecutorService绝对很棒。

如果您使用的是 Java EE 6 服务器,您可以从中获得一些乐趣,@Schedule并且ScheduleExpression

请参阅使用“crontab 语法”来安排 EJB 任务

于 2012-10-12T20:46:33.877 回答
0

另一个例子

import java.text.SimpleDateFormat;
import java.util.Date;

public class TestHour {

    private static final int MINUNTE = 20;

    public static void main(String args[]) {
        while (true) {
            SimpleDateFormat bartDateFormat = new SimpleDateFormat("mm");
            Date date = new Date();
            int currentMin = new Integer(bartDateFormat.format(date))
                    .intValue();
            if (currentMin < MINUNTE) {
                sleepMinutes(MINUNTE - currentMin);
            } else if (currentMin > MINUNTE) {
                sleepMinutes(60 - currentMin + MINUNTE);
            } else {
                // DO SOMETHING EVERY HOUR
                System.out.println("come on do it!!!");
                sleepMinutes(60);
            }
        }
    }

    private static void sleepMinutes(int minutes) {
        try {
            System.out.println("Sleeping for " + minutes);
            Thread.sleep(minutes * 1000*60);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
于 2012-10-12T20:58:07.610 回答
0

今天学到的东西又是另一个例子。

import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class SchedulerExample2 implements Runnable{

    public static void main(String args[]) {

        Calendar due = Calendar.getInstance();
        due.set(Calendar.MILLISECOND, 0);
        due.set(Calendar.SECOND, 0);
        due.set(Calendar.MINUTE, 20);
        if (due.before(Calendar.getInstance())) {
            due.add(Calendar.HOUR, 1);
        }
        long milliSecondsToNextOcurrence =  due.getTimeInMillis() - new Date().getTime();
        final ScheduledExecutorService s = Executors.newSingleThreadScheduledExecutor();
        ShedulerExample task = new  ShedulerExample();
        s.scheduleAtFixedRate(task, milliSecondsToNextOcurrence, 60*60*1000, TimeUnit.MILLISECONDS);
    }

    @Override
    public void run() {
            System.out.println("hola->"+new Date());
    }   
}
于 2012-10-12T21:28:07.003 回答