ホームページ  >  記事  >  Java  >  Java DelayQueue は遅延タスクをどのように実装しますか?

Java DelayQueue は遅延タスクをどのように実装しますか?

WBOY
WBOY転載
2023-05-13 16:40:061736ブラウズ

1. DelayQueue の適用原理

DelayQueue は、制限のない BlockingQueue の実装クラスであり、Delayed インターフェイスを実装するオブジェクトを配置するために使用されます。オブジェクトは、有効期限が切れたときにのみキューから取得できます。 。

BlockingQueue はブロッキング キューであり、Java によって提供されるマルチスレッド セーフなキュー データ構造です。キュー内の要素の数が 0 の場合、キューから要素を取得しようとするスレッドはブロックされるか、スローされます。例外。

ここでの「無制限」キューとは、キュー内の要素数に上限がなく、要素数の増加に応じてキューの容量が拡張されることを意味します。

Java DelayQueue は遅延タスクをどのように実装しますか?

DelayQueue は BlockingQueue インターフェイスを実装しているため、無制限とブロッキングの特性を備えています。さらに、独自のコア特性は次のとおりです。キューに置かれた遅延タスク オブジェクトは、遅延時間に達した後にのみ取得できます。"

.

DelayQueue は null 要素を受け入れません

「DelayQueue は java.util.concurrent.Delayed インターフェイスを実装するオブジェクトのみを受け入れます」

2. 順序遅延タスクの実装

DelayQueue の特性を理解した後、それを使用して遅延タスクを実装し、

java.util.concurrent.Delayed

インターフェイスを実装できます。

import org.jetbrains.annotations.NotNull;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * 延时订单任务
 */
public class OrderDelayObject implements Delayed {
  private String name;
  private long delayTime;   //延时时间
  //实际业务中这里传订单信息对象,我这里只做demo,所以使用字符串了
  private String order;

  public OrderDelayObject(String name, long delayTime, String order) {
    this.name = name;
    //延时时间加上当前时间
    this.delayTime = System.currentTimeMillis() + delayTime;
    this.order = order;
  }

  //获取延时任务的倒计时时间
  @Override
  public long getDelay(TimeUnit unit) {
    long diff = delayTime - System.currentTimeMillis();
    return unit.convert(diff, TimeUnit.MILLISECONDS);
  }

  //延时任务队列,按照延时时间元素排序,实现Comparable接口
  @Override
  public int compareTo(@NotNull Delayed obj) {
    return Long.compare(this.delayTime, ((OrderDelayObject) obj).delayTime);
  }

  @Override
  public String toString() {
    Date date = new Date(delayTime);
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    return "\nOrderDelayObject:{"
            + "name=" + name
            + ", time=" + sd.format(date)
            + ", order=" + order
            + "}";
  }
}
上記クラスの注文は注文情報オブジェクトであり、実際の事業開発では注文情報を渡して注文キャンセル業務を実装する必要があります(支払いが無い場合は自動的に注文がキャンセルされます) 30分間)。

Delayed インターフェイスは Comparable インターフェイスを継承しているため、「遅延時間」に従ってキュー内の遅延タスクを並べ替えるには、compareTo メソッドを実装する必要があります。

getDelay メソッドは遅延インターフェイス メソッドです。このメソッドを実装すると、遅延タスクを取得するためのカウントダウン時間が提供されます。

3. 注文処理

最初に、永続的に保存するコンテナーが必要です。遅延タスクキュー。Spring 開発環境であれば、これを行うことができます。

@Bean("orderDelayQueue")
public DelayQueue<OrderDelayObject> orderDelayQueue(){
    return new DelayQueue<OrderDelayObject>();
}

ユーザーが注文すると、注文タスクを遅延キューに入れます

@Resource
private DelayQueue<OrderDelayObject> orderDelayQueue;

//发起订单下单的时候将订单演示对象放入orderDelayQueue
orderDelayQueue.add(
        new OrderDelayObject(
                "订单延时取消任务",
                30 * 60 * 1000,    //延时30分钟
                "延时任务订单对象信息"
        )
);

システムでスレッドを開き、キューからメッセージを継続的に取得し、遅延メッセージが処理されます。

DelayQueue

の take メソッドは、キューから遅延タスク オブジェクトを取得します。キュー要素の数が 0 の場合、または「遅延時間タスク」に達していない場合、スレッドはブロックされます。

@Component
public class DelayObjectConsumer  implements InitializingBean {

  @Resource
  private DelayQueue<OrderDelayObject> orderDelayQueue;

  @Override
  public void afterPropertiesSet() throws Exception {
    while (true) {
      OrderDelayObject task = orderDelayQueue.take();
      System.out.println(task.toString());
      System.out.println(task.getOrder());
      //根据order订单信息,去查询该订单的支付信息
      //如果用户没有进行支付,将订单从数据库中关闭
      //如果订单并发量比较大,这里可以考虑异步或线程池的方式进行处理
    }
  }
}
ここでの while-true ループの遅延タスク処理はシーケンシャルに実行されることに注意してください。注文の同時実行数が比較的大きい場合、注文クローズ操作を完了するために非同期処理を考慮する必要があります。私は以前に SpringBoot 用の監視可能で簡単に構成可能なスレッド プール オープン ソース プロジェクトを作成しました。これは役立つかもしれません。ソース コード アドレス

は私によってテストされ、orderDelayQueue の遅延タスクに配置されています。 1時間後、正しい実行処理を取得します。これは、実装が正しいことを示しています。

4. 長所と短所

DelayQueue を使用して遅延タスクを実装するのは非常に簡単で便利です。すべては標準の JDK コードで実装されており、サードパーティの依存関係を導入する必要はありません ( Redis 実装、メッセージ キュー実装などに依存します)、非常に軽量です。

欠点は、すべての操作がアプリケーション メモリに基づいているため、アプリケーションの単一障害点が発生すると、遅延したタスク データが失われる可能性があることです。 DelayQueue に制限がないため注文の同時実行数が非常に多い場合、注文量が増えるとキュー内のオブジェクトも多くなり、OOM のリスクが発生する可能性があります。したがって、DelayQueue を使用して遅延タスクを実装することは、タスクの量が小さい状況にのみ適しています。

以上がJava DelayQueue は遅延タスクをどのように実装しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。