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.
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"
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 + "}"; } }
上文类中的order为订单信息对象,在实际的业务开发过程中应该是传递订单信息,用于取消订单业务的实现(订单30分钟不付款自动取消)。
Delayed接口继承自 Comparable接口,所以需要实现compareTo方法,用于延时任务在队列中按照“延时时间”进行排序。
getDelay方法是Delayed接口方法,实现该方法提供获取延时任务的倒计时时间
首先我们需要一个容器,永久保存延时任务队列,如果是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
@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订单信息,去查询该订单的支付信息 //如果用户没有进行支付,将订单从数据库中关闭 //如果订单并发量比较大,这里可以考虑异步或线程池的方式进行处理 } } }
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 deDelayQueue
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!