DelayQueue 实现单机延迟任务处理

前言

我们有一些项目需要单机获取延迟处理一些任务,延迟的时间并不长。也没有延迟队列支持,项目本身docker部署利用redis 实现又存在队列锁竞争问题,该资源也不是非常重要如果不小心丢失部分也无关紧要。当然也可以先存入数据库,项目启动将数据加载的内存中。

实践

1、配置线程池处理处理数据,可以根据自身内部数据多少配置线程池,不确定可以进行配置方式处理。

@Component
public class ParkingConfig {




    public static  DelayQueue<ImageDelay> queue = new DelayQueue<>();

    @Bean("getParkImage")
    public ExecutorService executor(@Autowired ApplicationContext ctx) {
       // final int processor = Runtime.getRuntime().availableProcessors();
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1, 10,
                TimeUnit.MINUTES, new ArrayBlockingQueue<>(1000));
        threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPool.setThreadFactory(runnable -> {
            Thread thread = new Thread(runnable);
            final String name = "getParkImage-" + thread.getName();
            thread.setName(name);
            return thread;
        });
        for (int i = 0; i < threadPool.getCorePoolSize(); i++) {
            threadPool.execute(new GetImageTask(ctx.getBean(ParkingTurnoverService.class)));
        }
        return threadPool;
    }
}

2、创建GetImageTask任务进行处理数据,这里用take 根据队列特性,如果队列为空直接阻塞线程,不需要做休眠处理。

@Slf4j
public class GetImageTask  implements Runnable {

    private ParkingTurnoverService parkingTurnoverService;

    public GetImageTask(ParkingTurnoverService parkingTurnoverService) {
        this.parkingTurnoverService = parkingTurnoverService;
    }

    @Override
    public void run() {
        log.info("get Image start");
        ImageDelay imageDelay = null;
        while (true) {
            try {
                imageDelay = ParkingConfig.queue.take();
                this.parkingTurnoverService.insertImage(imageDelay);
            } catch (Throwable e) {
                log.error("get image is fail", e);
            }
        }
    }
}

3、队列中需要存储需要处理的数据,DelayQueue 提供一个getDelay(TimeUnit unit) 做延迟实践的处理。

@Data
public class ImageDelay implements Delayed {

    /* 触发时间*/
    private long time;

    private Long id;

    private ImageEnum imageEnum;

    private Integer num;

    public ImageDelay(Long id, ImageEnum imageEnum, long time, TimeUnit unit) {
        this.id = id;
        this.imageEnum = imageEnum;
        this.time = System.currentTimeMillis() + (time > 0 ? unit.toMillis(time) : 0);
        this.num = 1;
    }


    @Override
    public long getDelay(TimeUnit unit) {
        return time - System.currentTimeMillis();
    }

    @Override
    public int compareTo(Delayed o) {
        ImageDelay item = (ImageDelay) o;
        long diff = this.time - item.time;
        if (diff <= 0) {
            return -1;
        }else {
            return 1;
        }
    }
}

4、放入数据处理,等待GetImageTask 对其进行处理

ImageDelay imageDelay = new ImageDelay(parkingTurnover.getId(), ImageEnum.IN, 3, TimeUnit.SECONDS);
ParkingConfig.queue.add(imageDelay);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kafka实现延迟任务的方法有多种。其中一种常见的方法是使用Kafka的延迟队列功能。在这种方法中,我们可以将任务消息发送到Kafka的一个特定主题,并为该消息设置一个延迟时间。当消息到达延迟时间后,Kafka会将消息推送到消费者进行处理。 具体的实现步骤如下: 1. 首先,我们需要创建一个Kafka的生产者,并配置好相关的参数,包括连接到Kafka集群的地址、序列化器等。 2. 接下来,我们可以定义一个任务对象,将任务的相关数据封装成一个消息对象。 3. 将任务消息发送到Kafka的延迟队列主题中,可以使用Kafka的Producer API提供的send方法。 4. 在消费者端,我们可以创建一个Kafka的消费者,并订阅延迟队列主题。 5. 当消费者接收到延迟队列中的消息时,可以根据消息中的任务数据执行相应的操作。 需要注意的是,Kafka的延迟队列功能是通过使用定时器、DelayQueue和ScheduledThreadPool等机制来实现的。而相比其他实现方式,Kafka的实现方式更加高效和可靠,因为它采用了槽的方式来管理延迟消息,避免了空推进的问题。 综上所述,Kafka可以通过设置延迟时间和使用延迟队列功能来实现延迟任务。这种方式在大数据技术生态中得到了广泛应用,并且具有高效和可靠的特点。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [kafka 延时消息处理](https://blog.csdn.net/cxu123321/article/details/108011694)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [大数据开发:Kafka延迟队列](https://blog.csdn.net/shuimuzh123/article/details/117530975)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [消息队列常见面试题 全解](https://download.csdn.net/download/Wis57/87916787)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值