任务调度是如何实现的?

发布于 2024-10-03 19:06:10 字数 282 浏览 2 评论 0原文

我已经做了很多工作来从 Web 服务检索一些数据,但现在遇到了调度请求的问题,我不太确定从哪里开始。

我监听 jms 队列中的事件,收到事件后,我需要在一段时间后向 Web 服务发出请求。持续时间根据事件属性而变化。如果 Web 服务返回 false,我需要继续安排请求,直到它返回 true。

我正在考虑在收到事件或错误响应时在队列上创建查找请求,但这似乎并不理想 - 我会不断地消耗消息,检查时间以查看是否应该发出请求如果没有,则将其放回到队列中。

如果有人对如何解决此类问题有建议,我将非常感激。

I've done a chunk of work to retrieve some data from a web service but now have the problem of scheduling requests to it and I'm not really sure where to begin.

I listen to a jms queue for events and upon receipt of an event I need to make a request to the web service after a duration. The duration varies depending on the event attributes. If the web service returns false I need to continue to schedule requests until it returns true.

I was thinking of creating a lookup request on a queue upon receipt of either an event or a false response, but this doesn't seem ideal - I'd be consuming messages constantly, checking the time to see if a request should be made yet and putting it back on the queue if not.

If anyone's got advice on how to implement such a problem I'd really appreciate it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

百思不得你姐 2024-10-10 19:06:10

首先,确保将事件按照需要执行的顺序保留在队列中。这将确保您只需要查看队列的头部即可了解何时应安排下一个事件。您可以为此使用 PriorityQueue

用于处理事件的线程将从该队列中轮询项目并处理它们。让它查看头部项目并查看何时需要运行下一个事件。选择一个对象用作锁定对象,并让主线程对该对象调用 Object.wait(long),并向该方法传递下一个事件需要运行之前的毫秒数。

如果有新线程进来,将其添加到队列中适当的位置。如果该项目位于队列的头部,则意味着线程需要更快地唤醒。在锁对象上调用Object.notifyAll()来唤醒处理线程。它将发现没有什么需要处理并返回睡眠状态适当的时间。

public class ProcessingQueue extends Thread {

  private PriorityQueue<Task> tasks;  

  private volatile boolean isRunning = true;

  public void addTask(Task t) {
    synchronized (this.tasks) {
      this.tasks.offer(t);
      // this call requires synchronization to this.tasks
      this.tasks.notifyAll();
    }
  }

  public void shutdown() {
    this.isRunning = false;
    synchronized (this.tasks) {
      this.notifyAll();
    }
  }

  public void run() {
    while (this.isRunning) {
      synchronized (this.tasks) {
        Task t = this.tasks.peek();
        // by default, if there are no tasks, this will wake every 60 seconds
        long millisToSleep = 60000;
        // getExecuteMillis() should return the time, in milliseconds, for execution
        if (t != null) millisToSleep = t.getExecuteMillis() - System.currentTimeMillis();
        if (millisToSleep > 0) {
          try {
            // this line requires synchronization to this.tasks
            // and the lock is removed while it waits
            this.tasks.wait(millisToSleep);
          } catch (InterruptedException e) {
          }
        }
        t = this.tasks.poll();
        if (t != null) {
          t.execute();
        }
      }
    }
  }
}

First, make sure that you keep the events in the queue in the order in which they need to be executed. This will ensure that you only need to look at the head of the queue to see when the next event should be scheduled. You can use a PriorityQueue for this.

Your thread for processing events will poll items off this queue and process them. Have it peek at the head item and see when the next event needs to be run. Pick an object to use as a locking object and have the main thread call Object.wait(long) on that object, passing the method the number of milliseconds until the next event needs to be run.

If a new thread comes in, add it to the queue in the appropriate place. If the item is at the head of the queue, this means that the thread needs to wake up sooner. Call Object.notifyAll() on the lock object to wake up the processing thread. It will see that there is nothing to process and go back to sleep for the appropriate amount of time.

public class ProcessingQueue extends Thread {

  private PriorityQueue<Task> tasks;  

  private volatile boolean isRunning = true;

  public void addTask(Task t) {
    synchronized (this.tasks) {
      this.tasks.offer(t);
      // this call requires synchronization to this.tasks
      this.tasks.notifyAll();
    }
  }

  public void shutdown() {
    this.isRunning = false;
    synchronized (this.tasks) {
      this.notifyAll();
    }
  }

  public void run() {
    while (this.isRunning) {
      synchronized (this.tasks) {
        Task t = this.tasks.peek();
        // by default, if there are no tasks, this will wake every 60 seconds
        long millisToSleep = 60000;
        // getExecuteMillis() should return the time, in milliseconds, for execution
        if (t != null) millisToSleep = t.getExecuteMillis() - System.currentTimeMillis();
        if (millisToSleep > 0) {
          try {
            // this line requires synchronization to this.tasks
            // and the lock is removed while it waits
            this.tasks.wait(millisToSleep);
          } catch (InterruptedException e) {
          }
        }
        t = this.tasks.poll();
        if (t != null) {
          t.execute();
        }
      }
    }
  }
}
格子衫的從容 2024-10-10 19:06:10

我同意使用 3-d party 库。我为此使用石英框架。
http://www.quartz-scheduler.org/

I agree with using 3-d party library. I use quartz framework for that.
http://www.quartz-scheduler.org/

诗化ㄋ丶相逢 2024-10-10 19:06:10

使用现有的 OSS 调度程序: http://java-source.net/open-source/job -scheduler

你总是可以自己推出,但我不推荐它。

调度程序的一个重要特性应该是它能够在重新启动/崩溃后幸存下来。

Use an existing OSS scheduler: http://java-source.net/open-source/job-scheduler

You can always roll you own, but I'd not recommend it.

One important feature of a scheduler should be that it survives restart/crash.

菊凝晚露 2024-10-10 19:06:10

我决定使用 Spring 任务调度已在版本 3 中引入。它提供池化、基于时间瞬间和间隔的调度,如果需要更多自定义,它有一个 cron 选项。我没有深入研究 Quartz 可以实现的目标,但它也提供了与 Quartz 的集成。

I've decided to go with Spring Task Scheduling which has been introduced in version 3. It offers pooling, scheduling based on both instants in time and intervals, and if more customisation is required it has a cron option. I didn't delve into the depths of what can be achieved with Quartz but it also offers integration with that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文