DelayQueue는 Delayed 인터페이스를 구현하는 객체를 배치하는 데 사용되는 제한되지 않은 BlockingQueue의 구현 클래스입니다. 객체는 만료될 때만 대기열에서 제거될 수 있습니다.
BlockingQueue는 Java에서 제공하는 다중 스레드 안전 대기열 데이터 구조인 차단 대기열입니다. 대기열의 요소 수가 0이면 대기열에서 요소를 얻으려는 스레드가 차단되거나 예외가 발생합니다.
여기서 "무제한" 대기열은 대기열의 요소 수에 상한이 없으며 요소 수가 증가함에 따라 대기열의 용량이 확장된다는 의미입니다.
DelayQueue는 BlockingQueue 인터페이스를 구현하므로 무제한 및 차단 특성을 갖습니다. 또한 자체 핵심 특성은 다음과 같습니다.
"큐에 배치된 지연된 작업 개체는 다음까지 대기열에 배치되지 않습니다. 지연 시간에 도달해야만 얻을 수 있습니다.”.
DelayQueue는 null 요소를 허용하지 않습니다
"DelayQueue는 java.util.concurrent.Delayed 인터페이스를 구현하는 객체만 허용합니다."
DelayQueue의 특성을 이해한 후 이를 사용하여 지연된 작업을 구현하고 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
사용자가 주문하면 주문 작업이 지연된 대기열에 배치됩니다.🎜rrreee🎜시스템에 스레드가 열려 대기열에서 지속적으로 메시지를 받아 지연된 메시지를 처리합니다.DelayQueue
의 take 메소드는 대기열에서 지연된 작업 개체를 가져옵니다. 대기열 요소 수가 0이거나 "지연 시간 작업"에 도달하지 않은 경우 스레드가 차단됩니다. 🎜rrreee🎜 여기서 while-true 루프의 지연된 작업 처리는 순차적으로 실행된다는 점에 유의해야 합니다. 주문 동시성이 상대적으로 큰 경우 주문 마감 작업을 완료하려면 비동기 처리를 고려해야 합니다. 나는 이전에 관찰 가능하고 구성하기 쉬운 SpringBoot용 스레드 풀 오픈 소스 프로젝트를 작성했는데, 이는 여러분에게 도움이 될 것입니다. 소스 코드 주소 🎜🎜테스트 후에 orderDelayQueue의 지연된 작업을 넣었고 올바른 결과를 얻었습니다. 30분 후에 처리를 실행합니다. 이는 우리의 구현이 정확하다는 것을 보여줍니다. 🎜🎜4. 장점과 단점🎜🎜DelayQueue를 사용하여 지연된 작업을 구현하는 것은 매우 간단하고 편리합니다. 모두 표준 JDK 코드로 구현됩니다. 제3자 종속성을 도입할 필요가 없습니다(redis 구현, 메시지 대기열에 의존하지 않음). 구현 등) 매우 가벼운 클래스입니다. 🎜🎜 단점은 모든 작업이 애플리케이션 메모리를 기반으로 한다는 점입니다. 애플리케이션 단일 실패 지점이 발생하면 지연된 작업 데이터가 손실될 수 있습니다. 주문 동시성이 매우 큰 경우 DelayQueue가 무제한이므로 주문량이 많을수록 대기열에 있는 개체가 많아져 OOM 위험이 발생할 수 있습니다. 따라서 지연된 작업을 구현하기 위해 DelayQueue를 사용하는 것은 작업량이 작은 상황에만 적합합니다. 🎜위 내용은 Java DelayQueue는 지연된 작업을 어떻게 구현합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!