问题
I'm trying to implement a system in server that will do some updates on database on a ragular basis.
Here: Spawning threads in a JSF managed bean for scheduled tasks using a timer and in some other similar questions, I saw that BalusC strongly recommended to use Stateless Beans, if not possible SchedulerExecuterService rather than Timer.
Here is my situation. I need a JSF page in which I can configure the schedule interval. i.e. I can change its rule from run once in every 5 min to run once in 10 min
First, I tried to use @Schedule annotation and it was great. However, I couldn't find a way to change interval with that. First question, is it possible to change it dynamically like I told above?
I am currently using SchedulerExecutorService which is called from @PostConstruct of a Stateless Bean. Second question, is the Timer BalusC strongly recommended not to use is the TimerService of EJB?
Third Question, I liked the properties of timerService which is: using scheduleExpression and timerConfig. Are there any similar things for ScheduledExecutorService?
Additional Question: Am I on right track? Can the thing that I am trying to pull be done in a better way?
回答1:
I think @Schedule is used only for fixed cron-like timers, where the EJB container deploys a timer at EJB startup. You obviously need more dynamic scheduling connected with a JSF page.
If you are running on a full Java EE 6 profile, why not use the TimerService with a Stateless Session EJB like this:
@Stateless
public class JobSchedulerBean {
@Resource
private TimerService timerService;
// @PostConstruct
public void initTimer() {
// set initial timer
ScheduleExpression sch = new ScheduleExpression();
// set cron expression into sch
timerService.createCalendarTimer(sch, new TimerConfig("myTimer", false));
}
public void rescheduleTimer(int interval) {
// get timer from timer service
for (Timer timer : timerService.getTimers()) {
if (timer != null && timer.getInfo().equals("myTimer")) {
timer.cancel();
}
}
// schedule new timer, like in initTimer() method
}
@Timeout
public void timeout(Timer timer) {
// do the job
}
}
EDIT:
@ManagedBean(eager=true)
@ApplicationScoped
public class JobRunner {
private ScheduledExecutorService scheduler;
private static final int POOL_SIZE = 1;
ScheduledFuture<?> runHandle;
@PostConstruct
public void init() {
scheduler = Executors.newScheduledThreadPool(POOL_SIZE);
// set initial expiry to 5 minutes after 5 minutes delay
runHandle = scheduler.scheduleAtFixedRate(new MyJob(), 5, 5, TimeUnit.MINUTES);
}
@PreDestroy
public void destroy() {
scheduler.shutdownNow();
}
public void reschedule(int newDelay) {
// cancel old timer, but do not interrupt it
runHandle.cancel(false);
runHandle = scheduler.scheduleAtFixedRate(new MyJob(), newDelay, newDelay, TimeUnit.MINUTES);
}
}
public class MyJob implements Runnable {
public void run() {
// do the job
}
}
来源:https://stackoverflow.com/questions/24782699/scheduledexecutorservice-timerservice-and-stateless-ejb-on-scheduled-jobs