DelayQueue——延时队列做定时任务

@Data
public class ItemDelayed implements Delayed {
    private Long id;
    //触发时间
    private long time;
    //内容
    private String body;

    public ItemDelayed(){

    }
    public ItemDelayed(Long id,long time,String body, TimeUnit unit) {
        this.id = id;
        this.body = body;
        this.time = TimeUnit.NANOSECONDS.convert(time, TimeUnit.MILLISECONDS) + System.nanoTime();
    }

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

    @Override
    public int compareTo(Delayed o) {
        ItemDelayed item = (ItemDelayed) o;
        long diff = this.time - item.time;
        if (diff <= 0) {
            return -1;
        }else {
            return 1;
        }
    }
}
@Slf4j
public class BroadcastThread implements Runnable{
    private DelayQueue delayQueue;
    @Autowired(required = false)
    private BroadcastMapper broadcastMapper;

    /**
     * 封装queue
     * @param id 任务ID
     * @param duration 时长(天)
     * @param body 标题
     * @return
     */
    public BroadcastThread(Long id,Integer duration,String body){
        this.delayQueue = new DelayQueue();
        ItemDelayed item = new ItemDelayed();
        item.setId(id);
        item.setBody(body);
        Long exeTime = CommonTypeSwitch.getTimestampOfDateTime(LocalDateTime.now().plusDays(duration));
        item.setTime(exeTime);
        this.delayQueue.offer(item);
    }

    public BroadcastThread(DelayQueue delayQueue){
        this.delayQueue = delayQueue;
    }


    @Override
    public void run() {
        while (true) {
            try {
                ItemDelayed take = delayQueue.take();
                log.info("消费消息id:" + take.getId()+ " 消息体:" + take.getBody());
                //道具服务时间过期,修改广播列表 该任务等广播状态置为失效
                Broadcast entity = broadcastMapper.queryByTaskId(take.getId(),StatusEnum.BroadcastStatus.PROCESSING.getCode(),
                        StatusEnum.DflagStatus.VALID.getCode());
                if (null != entity){
                    Broadcast record = new Broadcast();
                    record.setStatus(StatusEnum.BroadcastStatus.OVER.getCode());
                    record.setId(entity.getId());
                    record.setUpdateTime(new Date());
                    record.setUpdateBy(ConstantValue.L_ZERO);
                    broadcastMapper.updateByPrimaryKeySelective(record);
                }
            } catch (InterruptedException e) {
                log.error("error:",e);
            }
        }
    }
}

如果发生断电情况,导致数据丢失,可以加上数据库,把需要发到延时队列到数据都存到数据库+版本(防止重复消费),每次重启项目扫描数据填充到队列里,删除数据库失败的不进行业务处理,或者先业务处理,删除失败回滚业务(业务也要有版本,防止重复操作)

 

 

你可能感兴趣的:(java,队列)