Heim  >  Artikel  >  Java  >  Wie implementiert Java DelayQueue verzögerte Aufgaben?

Wie implementiert Java DelayQueue verzögerte Aufgaben?

WBOY
WBOYnach vorne
2023-05-13 16:40:061726Durchsuche

1. Anwendungsprinzip von DelayQueue

DelayQueue ist eine unbegrenzte BlockingQueue-Implementierungsklasse, die zum Platzieren von Objekten verwendet wird, die die Delayed-Schnittstelle implementieren. Die darin enthaltenen Objekte können nur aus dem System entfernt werden wenn sie ablaufen. Abholung aus der Warteschlange.

BlockingQueue ist eine blockierende Warteschlange, eine von Java bereitgestellte Multithread-sichere Warteschlangendatenstruktur. Wenn die Anzahl der Elemente in der Warteschlange 0 ist, wird der Thread, der versucht, Elemente aus der Warteschlange abzurufen, blockiert oder eine Ausnahme auslösen.

Die „unbegrenzte“ Warteschlange bedeutet hier, dass es keine Obergrenze für die Anzahl der Elemente in der Warteschlange gibt und die Kapazität der Warteschlange mit zunehmender Anzahl der Elemente zunimmt.

Wie implementiert Java DelayQueue verzögerte Aufgaben?

DelayQueue implementiert die BlockingQueue-Schnittstelle und verfügt daher über die Eigenschaften Unbegrenzt und Blockierend. Darüber hinaus sind seine eigenen Kerneigenschaften:

# 🎜🎜#

„Das in der Warteschlange platzierte verzögerte Aufgabenobjekt kann erst abgerufen werden, nachdem die Verzögerungszeit erreicht ist“ .

DelayQueue akzeptiert keine Nullelemente

「DelayQueue akzeptiert nur Objekte, die die java.util.concurrent.Delayed-Schnittstelle implementieren」#🎜🎜 #2. Implementierung verzögerter Aufgaben

Nachdem wir die Eigenschaften von DelayQueue verstanden haben, können wir damit verzögerte Aufgaben implementieren und java.util.concurrentimplementieren >Schnittstelle.

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
            + "}";
  }
}

Die Bestellung in der obigen Klasse ist das Bestellinformationsobjekt. Im eigentlichen Geschäftsentwicklungsprozess sollten die Bestellinformationen übergeben werden, um das Auftragsstornierungsgeschäft zu implementieren (die Bestellung wird automatisch storniert, wenn dies der Fall ist). 30 Minuten nicht bezahlt). java.util.concurrent.Delayed接口。

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

上文类中的order为订单信息对象,在实际的业务开发过程中应该是传递订单信息,用于取消订单业务的实现(订单30分钟不付款自动取消)。

Delayed接口继承自 Comparable接口,所以需要实现compareTo方法,用于延时任务在队列中按照“延时时间”进行排序。

getDelay方法是Delayed接口方法,实现该方法提供获取延时任务的倒计时时间

三、订单处理

首先我们需要一个容器,永久保存延时任务队列,如果是Spring开发环境我们可以这样做。

@Resource
private DelayQueue<OrderDelayObject> orderDelayQueue;

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

当用户下单的时候,将订单下单任务放入延时队列

@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订单信息,去查询该订单的支付信息
      //如果用户没有进行支付,将订单从数据库中关闭
      //如果订单并发量比较大,这里可以考虑异步或线程池的方式进行处理
    }
  }
}

系统内开启一个线程,不断的从队列中获取消息,获取到之后对延时消息进行处理。DelayQueue

Die Delayed-Schnittstelle erbt von der Comparable-Schnittstelle, daher muss die CompareTo-Methode implementiert werden, um verzögerte Aufgaben in der Warteschlange nach „Verzögerungszeit“ zu sortieren.

Die getDelay-Methode ist eine verzögerte Schnittstellenmethode.

3. Auftragsverarbeitung

🎜🎜#Zuerst Wir benötigen einen Container, der die Warteschlange für verzögerte Aufgaben dauerhaft speichert. Wenn es sich um eine Spring-Entwicklungsumgebung handelt, können wir dies tun.

rrreee

Wenn der Benutzer eine Bestellung aufgibt, wird die Aufgabe zur Auftragserteilung in die Verzögerungswarteschlange gestellt.

rrreee

Ein Thread wird im System geöffnet, um kontinuierlich Nachrichten aus der Warteschlange abzurufen und Die verzögerte Nachricht wird nach dem Eintreffen verarbeitet. Die take-Methode von DelayQueue ruft das verzögerte Aufgabenobjekt aus der Warteschlange ab. Wenn die Anzahl der Warteschlangenelemente 0 ist oder die „Verzögerungszeitaufgabe“ nicht erreicht wurde, wird der Thread blockiert.

rrreee#🎜🎜#Es ist zu beachten, dass die verzögerte Aufgabenverarbeitung der while-true-Schleife hier sequentiell ausgeführt wird. Wenn die Auftragsgleichzeitigkeit relativ groß ist, muss eine asynchrone Verarbeitung in Betracht gezogen werden, um den Auftragsabschlussvorgang abzuschließen. . Ich habe zuvor ein beobachtbares und leicht konfigurierbares Thread-Pool-Open-Source-Projekt für SpringBoot geschrieben, das für Sie hilfreich sein könnte. Die Quellcode-Adresse lautet #🎜🎜##🎜🎜#. Nach meinen Tests habe ich die verzögerte Aufgabe von orderDelayQueue eingefügt Der korrekte Ausführungsprozess wurde nach einer halben Stunde erreicht. Es zeigt, dass unsere Umsetzung korrekt ist. #🎜🎜##🎜🎜# 4. Vor- und Nachteile#🎜🎜##🎜🎜#Die Verwendung von DelayQueue zum Implementieren verzögerter Aufgaben ist sehr einfach und bequem. Alle werden im Standard-JDK-Code implementiert, ohne dass Abhängigkeiten von Drittanbietern eingeführt werden auf Redis-Implementierung, Nachrichtenwarteschlangen-Implementierung usw.), sehr leichtgewichtig. #🎜🎜##🎜🎜# Der Nachteil besteht darin, dass alle Vorgänge auf dem Anwendungsspeicher basieren. Sobald ein Single Point of Failure der Anwendung auftritt, können verzögerte Aufgabendaten verloren gehen. Wenn die Auftragsgleichheit sehr groß ist, da DelayQueue unbegrenzt ist, gilt: Je größer das Auftragsvolumen, desto mehr Objekte befinden sich in der Warteschlange, was zu einem OOM-Risiko führen kann. Daher ist die Verwendung von DelayQueue zur Implementierung verzögerter Aufgaben nur für Situationen geeignet, in denen das Aufgabenvolumen gering ist. #🎜🎜#

Das obige ist der detaillierte Inhalt vonWie implementiert Java DelayQueue verzögerte Aufgaben?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen