Maison > Java > javaDidacticiel > Comment Java DelayQueue implémente-t-il les tâches retardées ?

Comment Java DelayQueue implémente-t-il les tâches retardées ?

WBOY
Libérer: 2023-05-13 16:40:06
avant
1791 Les gens l'ont consulté

1. Principe d'application de DelayQueue

DelayQueue est une classe d'implémentation de BlockingQueue illimitée, qui est utilisée pour placer des objets qui implémentent l'interface Delayed. Les objets ne peuvent être supprimés de la file d'attente que lorsqu'ils expirent.

BlockingQueue est une file d'attente de blocage, une structure de données de file d'attente multi-thread fournie par Java Lorsque le nombre d'éléments dans la file d'attente est 0, le thread essayant d'obtenir des éléments de la file d'attente sera bloqué ou lancera une exception.

La file d'attente « illimitée » signifie ici qu'il n'y a pas de limite supérieure sur le nombre d'éléments dans la file d'attente, et la capacité de la file d'attente augmentera à mesure que le nombre d'éléments augmente.

Comment Java DelayQueue implémente-t-il les tâches retardées ?

DelayQueue implémente l'interface BlockingQueue, il a donc les caractéristiques d'illimité et de blocage. De plus, ses propres fonctionnalités de base sont :

"L'objet tâche retardée placé dans la file d'attente sera placé dans la file d'attente après le. le temps de retard est atteint. Ce n’est qu’alors qu’il peut être obtenu ».

DelayQueue n'accepte pas les éléments nuls

"DelayQueue n'accepte que les objets qui implémentent l'interface java.util.concurrent.Delayed"

2. Implémentation de tâches de retard de commande

Après avoir compris les caractéristiques de DelayQueue, nous vous le ferons. peut l'utiliser pour implémenter des tâches retardées et implémenter l'interface java.util.concurrent.Delayed. 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
            + "}";
  }
}
Copier après la connexion

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

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

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

三、订单处理

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

@Bean("orderDelayQueue")
public DelayQueue<OrderDelayObject> orderDelayQueue(){
    return new DelayQueue<OrderDelayObject>();
}
Copier après la connexion

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

@Resource
private DelayQueue<OrderDelayObject> orderDelayQueue;

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

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

@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订单信息,去查询该订单的支付信息
      //如果用户没有进行支付,将订单从数据库中关闭
      //如果订单并发量比较大,这里可以考虑异步或线程池的方式进行处理
    }
  }
}
Copier après la connexion
La commande dans la classe ci-dessus est l'objet d'information de commande. Dans le processus de développement commercial réel, les informations de commande doivent être transmises pour mettre en œuvre l'activité d'annulation de commande (la commande sera automatiquement annulée si elle n'est pas payée pendant 30 minutes) .

L'interface Delayed hérite de l'interface Comparable, la méthode compareTo doit donc être implémentée pour trier les tâches retardées dans la file d'attente en fonction du « temps de retard ».

La méthode getDelay est une méthode d'interface retardée. L'implémentation de cette méthode fournit le temps de compte à rebours pour obtenir les tâches retardées

3 Traitement des commandes

Nous avons d'abord besoin d'un conteneur pour enregistrer définitivement la file d'attente des tâches retardées. S'il s'agit d'un environnement de développement Spring. , nous pouvons le faire .

rrreee

Lorsque l'utilisateur passe une commande, la tâche de passation de commande est placée dans la file d'attente retardée🎜rrreee🎜Un fil de discussion est ouvert dans le système pour obtenir en continu les messages de la file d'attente, puis traiter les messages retardés. La méthode take de DelayQueue obtient l'objet tâche retardée de la file d'attente. Si le nombre d'éléments de file d'attente est 0, ou si la "tâche de délai" n'a pas été atteinte, le thread sera bloqué. 🎜rrreee🎜Il convient de noter que le traitement différé des tâches de la boucle while-true est ici exécuté séquentiellement. Lorsque la simultanéité des commandes est relativement importante, un traitement asynchrone doit être envisagé pour terminer l'opération de clôture de la commande. J'ai déjà écrit un projet open source de pool de threads observable et facile à configurer pour SpringBoot, qui peut vous être utile. L'adresse du code source 🎜🎜Après mon test, j'ai mis la tâche retardée de orderDelayQueue et j'ai obtenu le résultat correct. après une demi-heure. Exécutez le traitement. Cela montre que notre implémentation est correcte. 🎜🎜4. Avantages et inconvénients🎜🎜L'utilisation de DelayQueue pour implémenter des tâches retardées est très simple et pratique. Toutes sont implémentées dans le code JDK standard. Il n'est pas nécessaire d'introduire des dépendances tierces (cela ne repose pas sur l'implémentation de Redis, ni sur la file d'attente de messages). implémentation, etc.), et c’est une classe très légère. 🎜🎜 Son inconvénient est que toutes les opérations sont basées sur la mémoire de l'application. Une fois qu'un point de défaillance unique de l'application se produit, les données de tâche retardées peuvent être perdues. Si la simultanéité des commandes est très importante, car DelayQueue n'est pas limité, plus le volume de commandes est grand, plus il y a d'objets dans la file d'attente, ce qui peut entraîner un risque de MOO. Par conséquent, l’utilisation de DelayQueue pour implémenter des tâches retardées ne convient que dans les situations où le volume de tâches est faible. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal